MySQL 8.0.36联合索引未生效?迁移后索引行为异常排查
MySQL 5.7迁移至8.0后联合索引选择差异原因分析
核心原因:优化器成本模型与统计逻辑更新
MySQL 8.0对查询优化器的成本估算体系做了大幅调整,同时统计信息的收集和使用逻辑也有迭代,这是导致索引选择差异的关键:
1. 联合索引前缀范围查询的成本评估变化
你的联合索引Index_EmpDataEmissao为(EMP_CODIGO, MINUTA_EMISSAO),当使用EMP_CODIGO > 0这类范围条件时:
- MySQL 5.7的优化器对该场景的成本估算偏低,会选择遍历联合索引中符合
EMP_CODIGO >0的部分,再过滤日期条件,即使该范围几乎覆盖全表数据。 - MySQL 8.0的优化器重新计算了成本:由于
EMP_CODIGO >0几乎匹配表中所有数据,优化器判定直接全表扫描的开销,要远低于遍历整个联合索引再执行回表操作的开销,因此放弃使用该索引。
而当使用EMP_CODIGO = 1等值条件时,联合索引的前缀列能精准定位数据范围,优化器可以快速筛选出该EMP下的目标日期数据,所以两个版本都会选择使用索引。
2. 单字段日期索引更优的逻辑
当你将索引改为仅包含MINUTA_EMISSAO后:
- 该索引的选择性更高,查询针对的是一个月的日期范围,优化器判定扫描这个索引的成本远低于全表扫描,同时回表后过滤
EMP_CODIGO >0的额外开销极小(因为该条件几乎不筛选数据)。 - 8.0的优化器对单字段范围索引的成本计算更精准,能识别到这类索引在该查询场景下的最优性。
优化建议
- 联合索引的前缀字段优先使用等值条件,才能最大化发挥索引效用;如果前缀字段是范围条件,后续字段的索引优势会失效。
- 当查询中核心过滤条件是某一范围字段(如日期),且其他范围条件的过滤性极差(如
EMP_CODIGO >0几乎覆盖全表),优先给核心范围字段建立单字段索引。 - 数据库迁移后建议重新收集统计信息:执行
ANALYZE TABLE TB_MINUTA;,确保优化器基于最新的表数据分布做决策。
内容的提问来源于stack exchange,提问作者Sergio PJ
相关产品推荐
相关产品推荐

