前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、优化器索引选择策略
选择索引是优化器的任务,但是优化器有的时候并没有那么智能 , 因此会出现索引选择错误的情况.
影响索引选择策略的问题有很多 , 比方说
- 扫描行数
- 是否需要使用临时表
- 是否已排序
- …
这里就引出一个问题了 ,
1.MySQL如何判断扫描行数的多少?
MySQL是通过索引区分度来判断选择哪个索引的. 索引的区分度其实就是该索引字段上不同值的个数,即 有多少个不同的值. 这个值越大 , 索引的区分度越高 , 被优化器选中的几率也越大
那么MySQL是如何得到这个值的呢? InnoDB会默认选中N
个数据页 , 统计其中的不同值数量,求平均值,再与这个索引的数据页数相乘得到结果; 当变更的数据行数超过1/M
时,会重新统计区分度
2.区分度持久化存储
MySQL通过innodb_stats_persistent
参数来控制是否需要持久化存储. 当参数值为on
时 , 统计信息会做持久化存储,此时上点中的N==20,M==10
,反之区分度存储在内存中,N==8,M==16
优化器误判原因
索引区分度并不是造成优化器误判的全部原因.
优化器会更具输入的索引区分度去预判扫描行数,正是这个预判操作造成了索引选中的偏差
同时回表的代价也会被考虑进去 , 综合上述原因造成了优化器的误判
二、索引选择的异常与处理应对
解决方案:
- 手动 选中一个合适索引
- 修改SQL语句 , 加入其它索引给优化器更多地选择
- 修改表结构 , 再增加一个合适的索引或删除误用的索引