mysql数据库中的缓存命中率与查询优化

来源:这里教程网 时间:2026-02-28 20:39:54 作者:

MySQL 查询缓存(query_cache)已彻底移除,别再查命中率了

MySQL 8.0 起,

query_cache_type
query_cache_size
等所有查询缓存相关变量已被删除。执行
SHOW VARIABLES LIKE 'query_cache%'
将返回空结果;设置它们会报错
Unknown system variable
。这意味着你无法再通过
Qcache_hits / (Qcache_hits + Qcache_inserts)
这类公式计算“查询缓存命中率”——因为那个缓存根本不存在了。

如果你还在监控

Qcache_hits
或依赖
mysqladmin extended -r -i 1 | grep Qcache
,说明你可能:

运行的是 MySQL 5.7 或更早版本(需尽快升级) 误把 InnoDB 缓冲池(
innodb_buffer_pool
)指标当成查询缓存指标
被过时的运维文档或监控脚本误导

真正该看的缓存:InnoDB 缓冲池命中率

InnoDB 缓冲池(

innodb_buffer_pool
)才是 MySQL 实际用到的核心缓存。它的“命中率”反映的是热数据是否常驻内存,直接影响磁盘 I/O 压力。计算公式为:

1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)

其中:

Innodb_buffer_pool_reads
:缓冲池未命中、必须从磁盘读取页的次数(越低越好)
Innodb_buffer_pool_read_requests
:总逻辑读请求数(包括命中和未命中)

健康阈值通常应 > 99%。低于 95% 就值得排查:

innodb_buffer_pool_size
是否太小?是否有大范围全表扫描?

实时查看命令示例:

mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%reads';"

没有查询缓存后,优化重点转向执行计划与索引

过去靠查询缓存“掩盖”慢查询,现在每条语句都真实执行。优化必须落到 SQL 层面:

EXPLAIN
检查
type
字段:避免
ALL
(全表扫描),优先
const
/
ref
/
range
确认
key
列是否用了预期索引;
key_len
是否符合联合索引最左匹配
警惕隐式类型转换:比如
WHERE user_id = '123'
(字段是
INT
)会导致索引失效
ORDER BY
LIMIT
组合时,确保排序字段在索引中覆盖,否则触发
Using filesort

一个典型陷阱:

SELECT * FROM orders WHERE status IN ('paid','shipped') ORDER BY created_at DESC LIMIT 20
—— 若没建
(status, created_at)
联合索引,即使
status
有单列索引,仍大概率走全表扫描+临时文件排序。

其他影响“感知性能”的缓存层不能忽略

应用端和中间件的缓存行为,往往比数据库内置机制更关键:

连接池(如 HikariCP)的
maxLifetime
idleTimeout
设置不当,会导致频繁重连,掩盖真实 SQL 性能问题
Redis 缓存穿透/雪崩会使大量请求直打 MySQL,此时看到的“慢查询”其实是缓存缺失引发的并发冲击 ORM 框架(如 MyBatis 的二级缓存、Hibernate 的
@Cache
)若未合理配置
timeToLiveSeconds
,可能返回陈旧数据,或因缓存击穿引发 DB 突增

查一条 SQL 很快,但线上接口 P99 延迟飙升?先确认是不是缓存层失效导致流量洪峰直接压到了 MySQL 连接数和缓冲池上。

相关推荐