虽然说现在的搜索范围是using where 是一个满足目前开发的一个效率,但我认为还是有可以优化的空间的。
目前是这样,有一个单列索引a,还有一个联合索引a_b_c
我们的查询条件是这样
select * from table where a = xx and b = xx and c = xx and d= xx and f = xx
有的查询还用到了like 不过那个字段也是索引的,还有用到了in的,也是上了索引的,这里就简化不说了。
目前用到的索引是 a。我就很纳闷,有单列索引a和联合索引a_b_c为啥不用联合索引?
联合索引怎么也比单列索引精度高啊!
或许我们不应该过于信任mysql的优化器。
这次比较单列索引a 和联合索引 a_b_c要看两个东西。
一个是rows 一个是filtered:符合某条件的记录数百分比。
目前索引是单列索引a,explain发现定位到的行数是:
rows:210
fitered:10
通过use index(a_b_c)强制使用联合索引,发现mysql需要对比
rows需要对比的行数:1035
fitered:3.13
type:all
key:null
好家伙 联合索引失效
这个联合索引为什么失效呢?顺便一说我为了实验的变量可控性
我使用的where里面的过滤字段只有a,b,c由于mysql版本,也没用‘>'来设置条件/
查了一下,有一种情况下索引会失效,mysql会认为走了全表
比如上面行数1035 但是一共表里数据就1100多条。
这种情况来看 即使a字段筛选度高也不该选用。
当然这也和我where 里面选择的值有关系,我设置的是 where a < max
这可不就走了全表。
换了个稍微小一点的值,rows没超过全部的百分之30,单列索引a又正常工作了。
但为什么没走联合索引?强制它走联合索引。
发现行数相同,命中率单列是7,联合是3.
总结:虽然说我们设置联合索引的时候,要选择区分度最高的,就像很多人很多博客都说过的那样,城市和性别一起做联合索引要把城市放前面。
事实上,当数据过于分散的情况下,拿城市做打头的也不太合适。
但是这不代表区分度越高越好,比如说时间戳非常不合适。
当你的时间戳字段排序好,当你要找的部分命中行数正好是前百分之30时这是可以正常工作的。但是查询时传值是由用户输入来决定的,并不知道用户会输入哪一段时间。
而且时间戳 bigint类型,还存在作为索引时,‘>'会失效的情况。很奇怪,虽然网上有人说这是由于mysql版本是5.7的原因,但是int类型索引,用‘>'并不会失效?
下一步就准备研究下这个问题,要是有大佬清楚为什么也麻烦告知。



