最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MySQL优化器为什么会选错索引以及如何强制干预
时间:2026-06-20 10:53:53 编辑:袖梨 来源:一聚教程网
ANALYZE TABLE 能快速修复选错索引,因为它通过重新随机采样索引页更新统计值(如 CARDINALITY、ROWS),使优化器基于真实数据分布选择索引;不生效的三大原因是持久化统计关闭、查询使用函数或隐式类型转换;FORCE INDEX 仅临时止血,根治需纳入巡检并监控统计偏差。
ANALYZE TABLE 为什么能快速修复选错索引
因为优化器不是靠“猜”,而是靠 CARDINALITY、ROWS 这些统计值估算成本。这些值来自采样,不是实时计算的。当表经历大批量写入或删除后,采样结果严重偏离真实分布,比如 city_id = 565 实际只匹配 200 行,但统计显示该值“高频”,优化器就放弃 idx_city_id_type,转而扫 8000w 行。
ANALYZE TABLE 会重新随机采样约 10–20 个索引页(可由 innodb_stats_persistent_sample_pages 调整),刷新 information_schema.STATISTICS 中的关键字段,让优化器看到真实数据分布。多数情况下,执行完就能让慢查询从秒级回落到毫秒级。
ANALYZE TABLE 不生效的三个典型原因
执行完 ANALYZE TABLE 后 EXPLAIN 没变?先排查这三点:
- 表开启了
innodb_stats_persistent = OFF,且innodb_stats_on_metadata = OFF,导致统计信息只存在内存里,重启或元数据操作后立即失效 - 查询中用了函数,比如
WHERE DATE(log_dt) = '2024-01-01',索引根本用不上,ANALYZE对失效索引无能为力 - 存在隐式类型转换,例如
city_id是INT,但传参是字符串'565',优化器被迫在列上加转换函数,索引失效
FORCE INDEX 是止血,不是根治
线上告警压顶时,SELECT * FROM t FORCE INDEX (idx_city_id_type) WHERE city_id = 565 能立刻生效,但它掩盖了真正的问题:
- 绕过优化器决策,一旦某
city_id数据量暴涨十倍,强制走索引反而更慢 - SQL 硬编码索引名,后续删索引或改名会直接报错
ERROR 1176 (HY000): Key 'xxx' doesn't exist in table 't' - 其他没加
FORCE的查询依然受错误统计影响,问题只是被局部压制
统计不准这件事本身没有日志、不报错、不告警
它安静地拖垮性能,直到慢查询像雪崩一样涌进来。最危险的是你以为索引还在工作,其实优化器早已悄悄弃用。真正稳定的解法,是把 ANALYZE TABLE 加入运维巡检脚本,并监控 information_schema.STATISTICS.CARDINALITY 的波动趋势——偏差超过 30%,就自动触发重采样。
相关文章
- 御书屋自由阅读网入口_Po18浓情文直达页面推荐 06-20
- 新御宅屋_海棠书屋自由入口_在线阅读无需注册 06-20
- po18小说阅读网入口_收藏起来的私密可用地址 06-20
- 海棠书屋po18浓情文入口_老用户分享的稳定阅读页 06-20
- 入浓情自由PO18书屋在线看_真正可打开的备用站入口 06-20
- Po18御宅书屋秘书入口_现在还能访问的浓情文页面 06-20