MySQL为什么有时候会选错索引

当一条语句中涉及多个索引时,MySQL会选择使用哪个索引,但是有时候它选择的索引执行速度不是最优的(也就是优化器得到的优化结果不为最优)

  • 解决方案1:如果你知道使用哪个索引更好,可以使用**force index(a)**来指定sql语句强行使用某个索引,使用explain来查看sql执行情况
explain select * from t force index(a) where a between 10000 and 20000;

请添加图片描述

  • 解决方案2:使用analyze table t指令(具体看下面索引基数)

优化器选错索引的原因:主要是对采用每一个索引需要扫描的行数的错误预估(sql语句执行前,不能精确得出要扫描的行数,只有进行预估)

错误预估扫描行数的原因1:

MySQL根据索引的“区分度”来预估扫描行数,也就是索引上不同取值的个数(这个索引取值不同的记录行数,称为“基数”),基数越大索引的效率越高(索引树重复节点越少),使用以下指令可以查看每个索引的基数。

show index from table;

请添加图片描述

而在程序运行实时过程中,MySQL也不能精确的得到每个索引的基数,也是预估的,这里会产生偏差。

错误预估扫描行数的原因2:

使用主键索引时,只需要扫描一次表,使用非主键索引时,需要多次回表操作,此处总的扫描数就等于使用索引的一次扫描预估 + 每次回表的扫描预估,也会产生对扫描行数的错误预估。

对于以上由于索引基数预估错误导致的优化器优化失败,可以在执行sql前使用analyze table t指令,让数据库精确计算一次各个索引的基数。

请添加图片描述

但是一般情况下数据库的数据在实时变动,其索引的基数也是实时变动的,所以我觉得这个方法也有一定的局限性。

综上两点:MySQL优化器错误选取索引的原因归根结底是错误预估执行sql需要扫描的记录行数

当然以上考虑的都是优化器主要以扫描行数为选取索引的判断依据的情况,实际上优化器还会结合是否使用临时表、是否排序等因素进行综合判断。所以实际中一般是出现了慢查询后,除了采用以上两种方法外,根据具体情况再采用其他处理方法。

感觉对于数据库索引的选择这个点涉及很深的MySQL原理,这里我的总结分析也是走马观花,根据原作者说需要深入源码研究,还不是目前我能接收的哈哈,这里就先简单记录一下,以后有机会了再回过头来研究研究。

最后再次感谢丁奇大佬的技术分享:

https://time.geekbang.org/column/article/71173
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值