MySQL查询缓存原理与实战代码,揭秘数据库性能优化技巧

文章导读
MySQL查询缓存是一种高效的缓存机制,它会缓存SELECT查询的结果,当相同的查询再次执行时,直接从缓存中返回结果,避免重复执行查询,从而显著提升性能。实战中,可以通过SET GLOBAL query_cache_type=1开启查询缓存,查询语句需使用SQL_CACHE提示,如SELECT SQL_CACHE * FROM users WHERE id=1;监控缓存命中率用SHOW STATU
📋 目录
  1. 查询缓存开启与配置
  2. 查询缓存工作流程
  3. 性能监控与调优实战
  4. 查询缓存失效原因及规避
  5. 高级优化代码示例
  6. 查询缓存的局限性
A A

MySQL查询缓存是一种高效的缓存机制,它会缓存SELECT查询的结果,当相同的查询再次执行时,直接从缓存中返回结果,避免重复执行查询,从而显著提升性能。实战中,可以通过SET GLOBAL query_cache_type=1开启查询缓存,查询语句需使用SQL_CACHE提示,如SELECT SQL_CACHE * FROM users WHERE id=1;监控缓存命中率用SHOW STATUS LIKE 'Qcache%';,命中率高时效果明显。优化技巧包括调整query_cache_size大小为64M,并确保表结构不变以维持缓存有效性。

查询缓存开启与配置

在my.cnf配置文件中添加query_cache_type=1和query_cache_size=128M,然后重启MySQL生效。实战代码示例:SELECT SQL_CACHE count(*) from orders where status='pending'; 这样相同的查询下次直接命中缓存。注意,查询缓存对表更新敏感,UPDATE或DELETE会失效相关缓存。

查询缓存工作流程

MySQL收到SELECT查询时,先计算query_cache_key(包括SQL文本、数据库、客户端协议等),查缓存表(hash表),命中则返回,否则执行查询并存入缓存。缓存存储在query_cache_size指定的内存块中,使用LRU算法管理。实战中,避免动态SQL如带用户输入的查询,因为key不同无法命中。

MySQL查询缓存原理与实战代码,揭秘数据库性能优化技巧

性能监控与调优实战

使用SHOW STATUS LIKE 'Qcache_hits'; 和 Qcache_queries_in_cache; 计算命中率=Qcache_hits/(Qcache_hits+Qcache_inserts)。如果命中率低于50%,考虑增大query_cache_limit(单查询缓存上限,默认1M)。代码:mysql> SHOW VARIABLES LIKE 'query_cache%'; 查看配置。实际生产中,对于读多写少的场景,查询缓存可提升QPS数倍。

查询缓存失效原因及规避

查询缓存会因表schema变更、表数据修改、权限变化而整体或部分失效。实战技巧:使用读写分离,slave库开启查询缓存,主库关闭;或针对热点查询预热缓存,如应用启动时执行常见SELECT SQL_CACHE。示例代码:SET SESSION query_cache_type=ON; 针对会话开启。

高级优化代码示例

-- 开启查询缓存 SET GLOBAL query_cache_type = 1; SET GLOBAL query_cache_size = 268435456; -- 256M -- 查询示例 SELECT SQL_CACHE id, name FROM products WHERE category_id = 10 LIMIT 100; -- 检查缓存 SHOW STATUS LIKE 'Qcache%'; -- 清除缓存 RESET QUERY CACHE;

MySQL查询缓存原理与实战代码,揭秘数据库性能优化技巧

查询缓存的局限性

MySQL 8.0已移除查询缓存,因为它在多核环境下锁竞争严重,且Prepared Statement不命中。实战建议:迁移到ProxySQL或应用层缓存如Redis。对于5.7及以下版本,仍是读密集场景利器。

FAQ
Q: 如何判断查询缓存是否有效?
A: 执行SHOW STATUS LIKE 'Qcache_hits'; 如果hits远大于inserts,则有效。
Q: 查询缓存为什么突然失效?
A: 表被UPDATE/DELETE或DDL操作,会清空相关或全局缓存。
Q: MySQL 8.0还有查询缓存吗?
A: 没有,已移除,推荐用其他缓存方案。
Q: 如何强制不使用查询缓存?
A: 在查询加SQL_NO_CACHE提示,如SELECT SQL_NO_CACHE * FROM table;