MySQL数据库之分析MySQL中优化distinct的技巧
小标 2019-02-27 来源 : 阅读 1207 评论 0

摘要:本文主要向大家介绍了MySQL数据库之分析MySQL中优化distinct的技巧 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助。

本文主要向大家介绍了MySQL数据库之分析MySQL中优化distinct的技巧 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助。

MySQL数据库之分析MySQL中优化distinct的技巧

有这样的一个需求:select count(distinct nick) from user_access_xx_xx;

这条sql用于统计用户访问的uv,由于单表的数据量在10G以上,即使在user_access_xx_xx上加上nick的索引,

通过查看执行计划,也为全索引扫描,sql在执行的时候,会对整个服务器带来抖动;


root@db 09:00:12>select count(distinct nick) from user_access; +———————-+ | count(distinct nick) | +———————-+ |        806934 | +———————-+ 1 row in set (52.78 sec)    

执行一次sql需要花费52.78s,已经非常的慢了

现在需要换一种思路来解决该问题:

我们知道索引的值是按照索引字段升序的,比如我们对(nick,other_column)两个字段做了索引,那么在索引中的则是按照nick,other_column的升序排列:

我们现在的sql:select count(distinct nick) from user_access;则是直接从nick1开始一条条扫描下来,直到扫描到最后一个nick_n,

那么中间过程会扫描很多重复的nick,如果我们能够跳过中间重复的nick,则性能会优化非常多(在oracle中,这种扫描技术为loose index scan,但在5.1的版本中,mysql中还不能直接支持这种优化技术):

所以需要通过改写sql来达到伪loose index scan:

root@db 09:41:30>select count(*) from ( select distinct(nick) from user_access)t ; | count(*) | +———-+ |  806934 | 1 row in set (5.81 sec)    

Sql中先选出不同的nick,最后在外面套一层,就可以得到nick的distinct值总和;

最重要的是在子查询中:select distinct(nick) 实现了上图中的伪loose index scan,优化器在这个时候的执行计划为Using index for group-by ,

需要注意的是mysql把distinct优化为group by,它首先利用索引来分组,然后扫描索引,对需要的nick只扫描一次;

两个sql的执行计划分别为:

优化写法:


 root@db 09:41:10>explain select distinct(nick) from user_access-> ; +—-+————-+——————————+——-+—————+————-| id | select_type | table            | type | possible_keys | key               | key_len | ref | rows  | Extra          | +—-+————-+——————————+——-+—————+————- | 1 | SIMPLE   | user_access | range | NULL     | ind_user_access_nick | 67   | NULL | 2124695 | Using index for group-by | +—-+————-+——————————+——-+—————+————-    

原始写法:


root@db 09:42:55>explain select count(distinct nick) from user_access; +—-+————-+——————————+——-+—————+————- | id | select_type | table            | type | possible_keys | key            | key_len | ref | rows   | Extra    | +—-+————-+——————————+——-+—————+————- | 1 | SIMPLE   | user_access | index | NULL     | ind_user_access | 177   | NULL | 19546123 | Using index |    


本文由职坐标整理并发布,希望对同学们学习MySQL有所帮助,更多内容请关注职坐标数据库MySQL数据库频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程