Aurora MySQL未选用最优索引原因排查及优化咨询
Aurora MySQL优化器选低效索引的原因
核心原因:统计信息偏差+变量值无法预评估
Aurora MySQL的优化器依赖表统计信息估算执行成本,从你的EXPLAIN结果能看出明显的估算偏差:
- 使用
idx_electronic_latest_status_cancel_ticket时,优化器估算匹配latest_status='canceled' AND cancel_ticket IS NULL的行数为90168,实际却返回44847行,最终过滤后仅剩余97行。 - 使用
idx_electronic_bills_created_status_cancel_deleted时,优化器估算行数仅为1,与实际97行差距极大,说明统计信息可能过时或不准确。
另外,查询中使用了变量@DATE_CHECK,优化器生成执行计划时无法确定该变量的具体值,也就无法准确判断created_at >= @DATE_CHECK这个范围条件的过滤效果。这种情况下,优化器更倾向选择以等值条件开头的索引(即idx_electronic_latest_status_cancel_ticket),因为等值条件的行数估算通常更稳定,它误认为先定位等值条件的行再过滤范围条件会更高效,却忽略了实际中间结果集过大的问题。
索引结构的影响
idx_electronic_latest_status_cancel_ticket是基于两个等值条件的索引,优化器认为可以快速定位符合latest_status和cancel_ticket的行,再处理剩余的created_at和deleted_at过滤逻辑。但实际场景中,该索引返回的中间结果集过大,导致后续过滤耗时远超预期。idx_electronic_bills_created_status_cancel_deleted覆盖了所有四个过滤条件,但以范围列created_at开头。虽然该索引能直接定位到最终符合条件的行,但优化器对范围条件的行数估算严重失准,导致它误判该索引的执行成本更高。
可能的操作问题
左连接被隐式转为内连接
你使用了LEFT JOIN stores s,但后续添加了AND s.uses_system = 1条件。这会将左连接隐式转换为内连接(因为如果s不存在,s.uses_system =1为NULL,不满足条件)。如果业务逻辑确实需要内连接,建议显式改为INNER JOIN,避免语义混淆,同时帮助优化器更准确地估算连接成本。统计信息未及时更新
你的表有500万条记录,若存在频繁的增删改操作,统计信息极易过时。执行ANALYZE TABLE electronic_bills;可重新生成统计信息,帮助优化器更准确地判断索引的执行效率。变量使用干扰优化判断
@DATE_CHECK变量导致优化器无法在计划阶段评估范围条件的过滤效果。如果该变量的值固定或可提前确定,尝试替换为字面量,或使用预处理语句绑定参数,看是否能让优化器自动选择更高效的索引。
参考方向
- 复合索引设计:遵循「等值条件前置,范围条件后置」的基本原则,但若范围条件过滤性极强,可灵活调整;了解MySQL如何利用复合索引处理范围+等值的组合条件。
- EXPLAIN ANALYZE解读:通过实际执行时间、行数与优化器估算值的差异,判断统计信息是否准确、索引是否适配查询需求。
- Aurora MySQL优化器逻辑:与原生MySQL核心逻辑一致,依赖统计信息进行成本估算,重点关注统计信息更新机制和成本模型的细节。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

