1. 优化器的逻辑
优化器选择索引的判断因素:扫描的行数、是否使用临时表、是否排序等
1.1 扫描行数怎么计算
MySQL真正执行语句之前,并不能精确地的知道满足这个条件的记录有多少条,而只能通过统计信息来估算记录数。这个统计信息就是索引的“区分度”。
一个索引上不同的值越多,这个索引的区分度越好。索引上不同的值的个数,称为**“基数(cardinality)”**,即基数越大,索引的区分度越好。以下语句可以查看区分度
show index from m;
执行结果如下图所示:
InnoDB默认会选择N个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引页的页面数,得到这个索引的基数。当表中数据行超过1/M时,会重新触发一次索引统计。
通过设置参数innodb_stats_persistent的值:
- 设置为on时,表示统计信息会持久化存储。这时默认的N为20,M为10
- 设置为off时,表示统计信息只存储在内存,默认N是8,M是16
使用语句analyze table t
可以重新统计索引信息。
2. 索引选择异常处理
- 使用
force index
强行选择一个索引。 - 修改SQL语句,引导mysql使用我们期望的索引。
- 新建索引或者删掉误用的索引