灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:11217回复:0

[mysql]MySQL优化器中一个Count和覆盖索引的问题

楼主#
更多 发布于:2013-05-25 15:10

MySQL优化器中一个Count和覆盖索引的问题
 

图片:624268.jpg


 
现象说明
       其实这里主要要说明的是一个优化器还需要改进的地方。
 
优化器会根据where条件和select_list里面的字段决定在使用一个索引(sta)后,是否需要回表—回到聚集索引取数据。
 
基本的做法是:在确定了一个索引后,将select_list和where中出现的所有字段都拿来判断一下,如果字段都存在于sta索引中,则可以使用覆盖索引。
 
第一个explan可以用上覆盖索引(Using Index),
是因为select_list里面只有count(*),而count(*)在语法解析阶段就被特殊处理,不作为特殊字段。
 
第二个字段在现在的实现中,因为gmt不是sta索引的一部分(sta索引定义上只有sta一个字段,算上聚集索引结构,就是sta,auci)。所以最后判定为不能使用覆盖索引。
 
性能差别
         表中放入500w数据以后,这两个查询的时间相差25倍(0.19s vs  5s)。
 
存在改进
        
 其实我说这个“不科学”,是因为第二个语句居然不能使用覆盖索引。按照count(gmt)的语义,是计算gmt不为NULL的所有行的数目。但是表定义中,分分明已经说明了gmt为not
null。那么就可以转成count(*)了!
     目前因为count、sum、count(distinct)这些操作的处理方法被揉在一起,因此没有特别分开。
 
应用警惕
         好在按照正常的习惯,需要计算总数时,最多是count(auci)或者count(*),
不会故意去count一个别的字段。当时若使用的是MyISAM,就需要小心了。
 
        
 从上面的分析可以推测得到,如果这是个MyISAM表,还是一样的where条件,count(*)是可以使用覆盖索引的,但是count(auci)就不行了。
 

图片:796906.jpg


喜欢0 评分0
游客

返回顶部