面试中,当面试官问出这个问题时,你觉得这是在考察mysql的什么内容?我当时脑子过了一下,我知道一条sql在执行的时候,会经过查询缓存,sql解析器,预处理器,sql优化器,生成执行计划,调用存储过程的api,数据,这样一个大概过程。mysql在选择索引是在sql优化器这一步,但是具体如何选择索引的,我并没有读过源码,所以这个问题就GG了。
回家后,我还在想这题到底考察的什么,并且查了一些资料,搞清楚了选择是怎么一回事。在不考虑临时表和排序的情况下,优化器的目的是通过选择合适索引找到扫描数据行数最少的方案,即选择“选择性”较高的索引。选择性=基数/数据总数。索引基数是数据列所包含的不同值的数量。扫描行多少涉及到索引“基数”,但是“基数”通过采样来统计,本身是估算出来的而且不是实时的,索引数据不够精准,导致最终选出的方案在优化器看来最优,但实际执行起来并不是最优。 mysql 优化器最终选择哪个索引,需要具体采样数据来决定的,我们并不能看出来或者算出来。
但是优化器如果因为不准确的采样基数,无法选择最优索引怎么办? 这道题引申出的考察点如何干预mysql选择索引。如何让 mysql 能选择我们为某个 sql 所设计的最优索引,而不会因为优化器选择其他索引导致性能问题。
方法一,在sql中通过 force index 指定索引,等于直接告诉优化器不要用你那不靠谱的采样了,就用这个索引吧。缺点就是耦合性太强,如果你换一个更好的index那你要去改sql了,维护麻烦。
方法二,analyze table,主动让让索引的基数重新计算一下。缺点,不够实时,不够灵活,你不看着点又会跑偏了。
方法三,找出老是被错误选择的索引,如果作用不是很大,简单粗暴,删除。整个世界就清爽了。
网友评论