MySQL查询进入statistics状态的具体原因是什么?
MySQL查询进入statistics状态的核心原因及排查方案
statistics是MySQL查询执行前优化器阶段的状态,该阶段优化器会收集所有涉及表的元数据、索引统计信息、存储引擎返回的行估算值,计算不同执行路径的成本以选出最优执行计划。如果查询长时间停留在该状态,通常是以下原因导致:
- 关联表数量过多:如果查询关联了7张以上的表,优化器需要遍历的关联组合成本计算量会呈指数级增长,直接导致停留时间拉长。可通过
EXPLAIN语句先确认查询关联的表数量,优先裁剪不必要的关联逻辑。 - 表统计信息陈旧:若关联表近期有大量增删改操作但未触发自动统计信息更新,优化器读取到的行数、索引基数等数据严重失真,会反复校验不同执行路径的成本。可执行
ANALYZE TABLE 目标表名手动更新统计信息验证是否恢复。 - 元数据锁阻塞:如果有其他长事务/DDL操作持有目标表的元数据锁(MDL),查询进入statistics阶段读取表元数据时会被阻塞,表现为长时间停留在该状态。可执行
SHOW PROCESSLIST确认是否存在其他处于Waiting for table metadata lock状态的线程。 - 优化器搜索深度配置过高:MySQL默认
optimizer_search_depth参数值为62,控制优化器遍历执行计划的搜索深度,多表关联场景下该值过大会导致计算量暴增。可临时调低参数测试:SET SESSION optimizer_search_depth = 16;,再执行相同查询验证耗时。 - 表碎片率过高:单表数据量超过千万且存在大量历史删除操作时,碎片率过高会导致存储引擎返回的行估算值偏差极大,优化器需要反复校准统计数据。可在业务低峰期执行
OPTIMIZE TABLE 目标表名整理碎片(该操作会锁表,小表可直接执行,大表建议用在线DDL工具操作)。
快速排查顺序
- 优先执行
SHOW PROCESSLIST排查MDL锁阻塞问题 - 用
EXPLAIN确认关联表数量,过多则优先优化查询逻辑或临时调低optimizer_search_depth - 手动更新所有关联表的统计信息后重试
- 检查表碎片率,超过30%则安排时间整理碎片
内容的提问来源于stack exchange,提问作者Robeel Hassan
相关产品推荐
相关产品推荐

