MySQL — 索引优化面试题

小龙 609 2022-05-31

对数据库使用多个索引匹配的经验

mysql调优是一个很大的过程,首先可以创建索引,在创建索引会考虑以下几个点:

  1. 覆盖索引(包含了要查询的所有字段),可以减少回表次数,MySQL5.6对覆盖索引做了一个优化,索引下推

  2. 索引下推: 对覆盖索引所覆盖的字段进一步的进行筛选,尽量减少回表次数,可以通过 Explain 查看 SQL执行计划时,通过 Extra(音译:X死chua)字段可以查看是否有回表:Using index 表示没有回表操作,null 表示进行了回表操作

  3. 数据都是存在硬盘上的,硬盘查询数据时会有随机读写,mysql 查询的时候很怕随机读写的,它有一个磁盘寻址的开销,我们可以把 MRR 打开(Mutil-range read)mysql5.6 提供的新特性,当作范围查询时,会查到一组ID,我们需要回表对这一组ID一个一个的去找,这种查找就是随机IO,MySQl在回表之前会把范围查询出来的这一组ID读取到一个 buffer 里面,然后进行排序,然后顺序的通过ID去查找(MySQL叶子节点间是双向链表连接的,这种顺序ID的查询速度是很快的) 通过MRR就把原来随机IO变为了顺序IO

  4. 对于普通索引,我们服务写多读少,并且服务队唯一性要求没那么高,或者我们的业务代码可以保证唯一性时,我们就可以用普通索引,普通索引可以用到 Change Buffer,Change Buffer 可以把写操作缓存下来,在我们读取的时候通h过 Merge 技术将这条数据合并到 Buffer Pool 里面,这样可以提高我们写入速度,还有内存命中率。

上面这些是我认为在创建索引的时候可以考虑的一些点;

如果索引走不上时,我们应该考虑那些方面

  1. 首先检查是不是我们的SQL写的有问题,比如:是否对索引字段进行了函数操作,或者连接查询时两个表的编码是否相同,再或者关联查询时两个字段的类型是否都相同

  2. 排除了SQL的问题我们可以去查看是不是索引统计有问题,有问题可以在空闲时通过 ANALYZE TABLE 重新统计索引信息

  3. 可能业务上用的增删操作比较多,可能造成内存空洞比较多,这些都有可能造成索引选择的问题

Explain 分析出来的索引一定是最优的吗?

不一定,Explain可能会选错索引,我们在使用索引的时候可能会涉及到回表操作,还有一些排序操作可能会走错

索引建的不好导致索引走的很差

  1. 如果碰到这个不走索引的情况,可以考虑使用 force index强制走一个索引,但这这是一中应急预案,force index 与数据库耦严重,如果迁移到其他数据库里面就不支持了,需要重新发布代码。

  2. 另外可以考虑最左原则 + 覆盖索引,考虑能不能把这个选错的索引字段给删掉


# mysql # InooDB优化