sql语句如下: select count(distinct phone) from user where DATE_FORMAT(DATE,'%Y-%m-%d') = '2017-11-22';
执行结果:+-----------------------------+
| count(distinct phone) |
+-----------------------------+
| 748032 |
+-----------------------------+
1 row in set (50 min 21.12 sec)
有啥子优化的方法吗?
8 个解决方案
#1
#建立一个非聚集索引在user表的date列上
create UNIQUE index CL_dt_user on `USER`(date)
select count(distinct phone) from user where date between '2017-11-22 00:00:00' and '2017-11-22 23:59:59'
#2
1. 在date字段上添加索引,不需要唯一索引,唯一索引的话,如果系统并发量高的话,其实是会添加失败的。
2. 使用between, 或者 <= 和 >= 这种方法,更好的是计算时间戳,时间戳是会走索引的,
3. 如果不改变索引的情况下,可以考虑让系统走唯一能标识用户的列,例如: 如果用户表主键有序且一个id代表一个用户,则可以统计时间段内的主键,差值,就可以统计注册量了,
4. 另外这条语句没看执行计划吧,先看看执行计划。50分钟,要么是数据量很大,要么每建立任何索引吧!
最近个人公众号《andyqian》上更新了不少,关于数据库优化,索引方面的文章,有兴趣可以来看看!应该对你有帮助!
2. 使用between, 或者 <= 和 >= 这种方法,更好的是计算时间戳,时间戳是会走索引的,
3. 如果不改变索引的情况下,可以考虑让系统走唯一能标识用户的列,例如: 如果用户表主键有序且一个id代表一个用户,则可以统计时间段内的主键,差值,就可以统计注册量了,
4. 另外这条语句没看执行计划吧,先看看执行计划。50分钟,要么是数据量很大,要么每建立任何索引吧!
最近个人公众号《andyqian》上更新了不少,关于数据库优化,索引方面的文章,有兴趣可以来看看!应该对你有帮助!
#3
select count(distinct phone) from user where date(DATE) = '2017-11-22'
#4
从50分钟这个时间看,你这查询已经和数据量没关系了,date字段上有索引没有?没有加上,如果没权限更改表结构,那通过代码或者其他方式使查询条件落在有索引的列上,至少要让有索引的列出现在查询条件中,海量数据查询不走索引这是...我也不知说什么好了。另外不要使用任何mysql函数,会使索引无效而进行全表扫描
#5
我来说两句吧
首先,第一句:
select嵌套,一先把所有2017-11-22的distinct的phone找出来,然后再count,或者先count,再distinct
当然,重点第二句:
换SSD!换SSD!换SSD!
尼玛我曾今抓破脑子想优化,有毛线用,换了个SSD,那酸爽.....哎,真是钱花到哪好到哪...
首先,第一句:
select嵌套,一先把所有2017-11-22的distinct的phone找出来,然后再count,或者先count,再distinct
当然,重点第二句:
换SSD!换SSD!换SSD!
尼玛我曾今抓破脑子想优化,有毛线用,换了个SSD,那酸爽.....哎,真是钱花到哪好到哪...
#6
where DATE_FORMAT(DATE,'%Y-%m-%d') = '2017-11-22'; 这样肯定全表扫描。字段不要用函数,重要的说3遍
#7
我建议你分两步:第一步建date 索引;
第二步:修改一下my.ini配置文件,innodb_buffer_pool_size 增大这个数值,同时logfile也要增大,这样你的时间会缩短。
我用相同的数据测试了一下,我用了443.31秒,因为我的硬件是笔记本2G内存,如果是服务器时间可以更短。
第二步:修改一下my.ini配置文件,innodb_buffer_pool_size 增大这个数值,同时logfile也要增大,这样你的时间会缩短。
我用相同的数据测试了一下,我用了443.31秒,因为我的硬件是笔记本2G内存,如果是服务器时间可以更短。
#8
感谢各位大神们的回复,已结贴给分
#1
#建立一个非聚集索引在user表的date列上
create UNIQUE index CL_dt_user on `USER`(date)
select count(distinct phone) from user where date between '2017-11-22 00:00:00' and '2017-11-22 23:59:59'
#2
1. 在date字段上添加索引,不需要唯一索引,唯一索引的话,如果系统并发量高的话,其实是会添加失败的。
2. 使用between, 或者 <= 和 >= 这种方法,更好的是计算时间戳,时间戳是会走索引的,
3. 如果不改变索引的情况下,可以考虑让系统走唯一能标识用户的列,例如: 如果用户表主键有序且一个id代表一个用户,则可以统计时间段内的主键,差值,就可以统计注册量了,
4. 另外这条语句没看执行计划吧,先看看执行计划。50分钟,要么是数据量很大,要么每建立任何索引吧!
最近个人公众号《andyqian》上更新了不少,关于数据库优化,索引方面的文章,有兴趣可以来看看!应该对你有帮助!
2. 使用between, 或者 <= 和 >= 这种方法,更好的是计算时间戳,时间戳是会走索引的,
3. 如果不改变索引的情况下,可以考虑让系统走唯一能标识用户的列,例如: 如果用户表主键有序且一个id代表一个用户,则可以统计时间段内的主键,差值,就可以统计注册量了,
4. 另外这条语句没看执行计划吧,先看看执行计划。50分钟,要么是数据量很大,要么每建立任何索引吧!
最近个人公众号《andyqian》上更新了不少,关于数据库优化,索引方面的文章,有兴趣可以来看看!应该对你有帮助!
#3
select count(distinct phone) from user where date(DATE) = '2017-11-22'
#4
从50分钟这个时间看,你这查询已经和数据量没关系了,date字段上有索引没有?没有加上,如果没权限更改表结构,那通过代码或者其他方式使查询条件落在有索引的列上,至少要让有索引的列出现在查询条件中,海量数据查询不走索引这是...我也不知说什么好了。另外不要使用任何mysql函数,会使索引无效而进行全表扫描
#5
我来说两句吧
首先,第一句:
select嵌套,一先把所有2017-11-22的distinct的phone找出来,然后再count,或者先count,再distinct
当然,重点第二句:
换SSD!换SSD!换SSD!
尼玛我曾今抓破脑子想优化,有毛线用,换了个SSD,那酸爽.....哎,真是钱花到哪好到哪...
首先,第一句:
select嵌套,一先把所有2017-11-22的distinct的phone找出来,然后再count,或者先count,再distinct
当然,重点第二句:
换SSD!换SSD!换SSD!
尼玛我曾今抓破脑子想优化,有毛线用,换了个SSD,那酸爽.....哎,真是钱花到哪好到哪...
#6
where DATE_FORMAT(DATE,'%Y-%m-%d') = '2017-11-22'; 这样肯定全表扫描。字段不要用函数,重要的说3遍
#7
我建议你分两步:第一步建date 索引;
第二步:修改一下my.ini配置文件,innodb_buffer_pool_size 增大这个数值,同时logfile也要增大,这样你的时间会缩短。
我用相同的数据测试了一下,我用了443.31秒,因为我的硬件是笔记本2G内存,如果是服务器时间可以更短。
第二步:修改一下my.ini配置文件,innodb_buffer_pool_size 增大这个数值,同时logfile也要增大,这样你的时间会缩短。
我用相同的数据测试了一下,我用了443.31秒,因为我的硬件是笔记本2G内存,如果是服务器时间可以更短。
#8
感谢各位大神们的回复,已结贴给分