mysql如何选择执行计划的成本与代价评估

2次阅读

cost 字段不可靠,仅为优化器基于统计信息估算的相对 I /O+CPU 代价,仅同 SQL 不同路径间可比,跨语句 / 表 / 版本无效,且不含网络、锁等待等运行时开销。

mysql 如何选择执行计划的成本与代价评估

EXPLAIN 输出里的 cost 字段到底靠不靠谱

MySQL 8.0.19+ 的 EXPLAIN FORMAT=TREEEXPLAIN FORMAT=JSON 会显示 cost 值,但它不是真实执行耗时,而是优化器基于统计信息估算的「I/O + CPU」相对代价。这个值只在同一条 SQL 的不同执行路径间有比较意义,跨语句、跨表、跨版本基本不可比。

  • cost 不含网络传输、锁等待、并发竞争等运行时开销
  • 统计信息过期(ANALYZE TABLE 没跑)会导致 cost 严重失真
  • 小表全表扫描 cost 可能比大表走索引还低——因为优化器认为随机 I/O 比顺序扫更贵

真正影响执行计划选择的关键参数

优化器不是只看 cost,还会受以下硬性规则和阈值驱动:

  • eq_range_index_dive_limit:当 IN 列表超过该值(默认 200),优化器跳过索引统计采样,直接按“全范围扫描”估算,容易误判走全表
  • range_optimizer_max_mem_size:控制范围扫描估算内存上限,超限后退化为粗略估算,cost 偏离实际
  • 索引基数(Cardinality)不准 → rows 预估错误 → cost 计算崩盘
  • 隐式类型转换 (如 WHERE varchar_col = 123)强制放弃索引,但 EXPLAIN 仍可能显示“Using index”,cost 却很低——这是假象

手动干预执行计划前必须验证的三件事

别急着加 FORCE INDEX 或改写 SQL,先确认底层是否真有问题:

  • SHOW INDEX FROM table_nameCardinality 是否接近真实行数;偏差 >30% 就要 ANALYZE TABLE
  • 执行 SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE,找 "best_covering_index""condition_filtering_pct",看优化器是否被过滤条件误导
  • 对比 EXPLAIN ANALYZE(MySQL 8.0.18+)的真实执行树,看哪一步的 actual_time 远超 estimated_cost 对应的预期
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'shipped' AND created_at > '2024-01-01';

cost 估算失效的典型信号

当出现以下任一现象,说明 cost 已不可信,得靠观测而非估算做决策:

  • EXPLAIN 显示走了索引,但 profilingperformance_schema.events_statements_history 显示 Handler_read_next 高到离谱
  • 相同 SQL 在从库上走索引,在主库上走全表(主从统计信息未同步)
  • rows 预估是 100,实际扫描 50 万行(Handler_read_rnd_next 爆增)
  • 加了 USE INDEX 后响应时间反而翻倍——说明优化器原本选的路径虽 cost 高,但实际更稳(比如避免临时表 / 文件排序)

优化器的 cost 是一张粗糙的地图,不是导航软件。它依赖统计信息的鲜度、配置参数的合理性、以及你没写的那些隐式假设。真正决定快慢的,永远是磁盘寻道次数、缓冲池命中率、和那条没被 EXPLAIN 显示出来的锁等待链。

星耀云
版权声明:本站原创文章,由 星耀云 2026-01-07发表,共计1379字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources