mysql中SQL执行过程中缓存命中率与性能分析

2次阅读

mysql 8.0 已彻底移除查询缓存,性能优化应聚焦 InnoDB Buffer Pool 命中率(innodb_buffer_pool_reads/innodb_buffer_pool_read_requests),而非过时的 Qcache 指标。

mysql中SQL执行过程中缓存命中率与性能分析

MySQL 查询缓存(Query Cache)已弃用,别再依赖它做性能优化

MySQL 8.0 已彻底移除 query_cache_type 和相关参数,5.7 是最后一个支持它的稳定版本。如果你还在查 Qcache_hitsQcache_inserts 这类状态变量,说明你可能正踩在一个过时的优化思路上——缓存命中率 ≠ 实际性能收益,尤其在写多读少或表频繁变更的场景下,查询缓存反而会成为锁争用瓶颈。

真正影响 SQL 执行性能的缓存层是 InnoDB Buffer Pool

现代 MySQL 性能分析应聚焦 innodb_buffer_pool_reads(物理磁盘读)与 innodb_buffer_pool_read_requests(逻辑读请求)的比值,这才是衡量「热数据缓存效果」的关键指标:

select    ROUND((1 - (ibp_reads / ibp_read_requests)) * 100, 2) AS buffer_pool_hit_rate FROM (   SELECT      VARIABLE_VALUE AS ibp_reads   FROM performance_schema.global_status    WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads' ) r CROSS JOIN (   SELECT      VARIABLE_VALUE AS ibp_read_requests   FROM performance_schema.global_status    WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests' ) req;
  • Innodb_buffer_pool_reads > 0 表示有磁盘 I/O,需关注是否 buffer pool 太小或查询未走索引
  • 命中率长期低于 95% 通常意味着 buffer pool 不足,或存在大量全表扫描
  • 该指标只反映页级缓存效果,不等同于“SQL 结果被缓存”,和旧版 Query Cache 完全无关

如何判断某条 SQL 是否真的从 Buffer Pool 中受益

单条语句无法直接看到“本次执行是否命中 Buffer Pool”,但可通过 EXPLaiN format=jsON + 执行前后状态差定位真实开销:

  • 先执行 SHOW STATUS LIKE 'Innodb_buffer_pool_read%'; 记下 Innodb_buffer_pool_read_requestsInnodb_buffer_pool_reads
  • 运行目标 SQL(确保无其他并发干扰)
  • 再次执行 SHOW STATUS,观察 Innodb_buffer_pool_reads 是否增加:若增加,说明有页未命中,触发了磁盘读
  • 配合 EXPLAIN FORMAT=json 查看 rows_examinedused_columns,确认是否走了预期索引

注意:Handler_read_* 系列状态(如 Handler_read_next)反映的是存储引擎扫描行为,不是缓存命中指标,勿混淆。

performance_schema 中可跟踪的缓存相关事件

想深入分析某类操作的内存/IO 模式,开启以下 instruments 后查 events_waits_history_long

UPDATE performance_schema.setup_instruments  SET ENABLED = 'YES', TIMED = 'YES'  WHERE NAME LIKE 'wait/io/file/innodb/%' OR NAME LIKE 'wait/synch/mutex/innodb/%';
  • 重点关注 wait/io/file/innodb/innodb_data_file —— 表示实际磁盘读写等待
  • wait/synch/mutex/innodb/buf_pool_mutex 高频出现?说明 buffer pool latch 争用严重,可能是 buffer pool 过大且未启用 innodb_buffer_pool_instances
  • 这些事件不会告诉你“缓存命中”,但能暴露缓存失效或争用的真实代价

Buffer Pool 的大小、实例数、预热策略、以及 SQL 是否能复用已有页帧,远比“缓存命中率”这个数字更能决定性能。盯着一个被废弃的指标,不如先确认你的 innodb_buffer_pool_size 是否设为物理内存的 50%–75%,以及有没有定期用 SELECT * FROM table LIMIT 1 类操作意外刷掉热页。

text=ZqhQzanResources