本文源自 极客网站 的某知名大佬讲mysql,整理一下心得和重点。
第10节 mysql为什么会选错索引
mysql索引选择策略
首先,我们必须了解到,mysql在选择索引时,优化器会从以下角度来考虑是否选择索引:
- 使用force index(a-name)会强制使用a-name的索引(强制);
- 根据统计条件对应的行数(行数越少越好,占用的CPU资源就少);
- 根据是否排序,及其排序要花费的时间;
- 回表[0]的代价。
下面来逐条讲解一下每条需要注意的情况:
除了第一条是强制执行某索引,其他条都是综合考虑,通过估值来确定是否选择索引以及选择哪个索引的问题。
第二条,mysql在选择行数时,会采样统计[1],根据统计信息估算在查询条件的范围内大概有多少条记录。而这个时候就需要依靠于索引的区分度,一个索引上不同的值越多,其区分度就越好。
所以在建立索引(或者前缀索引)时,既要考虑索引的占用页数大小,也要考虑索引的使用效能,即区分度。
第三条,因为索引都是排好序的,所以有索引的可以直接忽略掉这部分花费的时间的考虑。如果一个查询语句中,order by和where中都有的字段,会更偏向于该字段的索引,尽管此时where中有别的索引有更优的效果。
ps:
[0] 回表:从二级索引上取到值,到主索引查出整行数据,来看它是否满足条件。而前缀索引的回表率是非常恐怖的,所以这个索引需要考虑诸多因素。一般使用distinct某字段的前几个字符,最后算一下统计几个字符可以达到要求(一般覆盖率为95%就满足大多数要求)。
[1] 采样统计:因为整表统计代价太大,所以选择采样统计。而采样统计会默认选择N个数据页,统计这些页上不同值,得到一个均值,再乘以这个索引的页数,就得到了这个索引的基数。而当数据库变更数据超过1/M时,会自动重新做一次索引统计。参数为innodb_stats_persistent
,为on表示统计信息会持久化,此时默认N=20,M=10;为off时表示统计信息只存储于内存中,此时默认N=8,M=16。
[2] 慢查询:指查询超过指定参数long_query_time
对应的时间的查询。该值在my.cnf中有,也可以手动设值,set long_query_time=0,表示超过0秒的查询记为慢查询。
网友评论