mysql 的 query cachepostgresql 的 pg_prewarm核心功能、原理机制、使用建议、适用场景、对比分析
一、mysql 的 query cache(查询缓存)【已废弃】
功能概述
mysql 的 query cache 是一个用于缓存 sql 查询结果的全局缓存,当完全相同的 sql 被再次执行时,可以直接返回缓存结果,跳过解析、优化、执行流程。
原理机制
- 查询缓存的是 结果集(result set),不是执行计划。
- 只有完全相同的 sql 字符串(包括空格、大小写)才能命中缓存。
- 当表中的数据发生变化(如
insert/update/delete
),该表相关的缓存会全部失效。 - query cache 是全局唯一的,不分库表、用户,也不是线程局部缓存。
主要参数:
query_cache_type = 1 # 0=off, 1=on, 2=demand query_cache_size = 64m # 缓存总大小 query_cache_limit = 1m # 单条查询最大缓存
优缺点:
优点 | 缺点 |
---|---|
小型、读多写少场景命中率高,减少 cpu 和磁盘压力 | 易导致全局锁争用,数据一变即清空相关缓存,命中率低 |
查询速度可极大提升(只要 sql 和表数据都未变化) | 高并发写时性能下降严重,适得其反;多核扩展性差 |
注意事项:
- mysql 5.7 开始默认关闭,8.0 已完全移除(废弃)。
- 在现代系统中,推荐使用应用层缓存(如 redis)、proxy 层缓存或使用 innodb buffer pool(页缓存)而非 query cache。
二、postgresql 的 pg_prewarm(页级预热)
功能概述
postgresql 的 pg_prewarm
是一个 将表或索引数据加载进共享缓冲区(shared_buffers) 的扩展模块,常用于数据库重启后的 热数据预加载(预热),加快数据库“恢复访问性能”。
原理机制
- postgresql 使用 buffer pool(共享缓冲区) 管理数据页,冷启动时缓存为空。
pg_prewarm
可以将指定的表、索引页主动读取进缓存,避免冷启动时慢查询。- 可以搭配
auto_preload_libraries
自动在启动时加载,也可以定期 dump 热页信息并在启动恢复。
使用方式
-- 加载扩展 create extension if not exists pg_prewarm; -- 手动预热某表 select pg_prewarm('mytable'); -- 指定预热方式(可选:prefetch, read, buffer, read_async) select pg_prewarm('mytable', 'prefetch');
配合自动预热使用
- 开启插件:
shared_preload_libraries = 'pg_prewarm'
- 使用
pg_buffercache
+pg_prewarm
定期导出热数据页,在重启后恢复:
select * from pg_buffercache limit 10; -- 使用 extension 来结合自动恢复机制
优缺点:
优点 | 缺点 |
---|---|
明确、主动地提升关键数据表冷启动性能 | 非自动缓存,需额外维护策略与脚本 |
适合大表/索引重启预热,提升系统恢复性能 | 如果 shared_buffers 太小,效果有限 |
三、对比总结
特性 / 系统 | mysql query cache | postgresql pg_prewarm |
---|---|---|
缓存内容 | sql 查询结果 | 数据页(blocks) |
缓存粒度 | sql 层 | 存储层(页级别) |
命中条件 | sql 完全相同且数据未改动 | 无需精确 sql,可按表预热 |
一致性影响 | 高(数据更新后清除缓存) | 无影响(数据页始终一致) |
是否自动 | 可自动缓存 | 需手动或脚本维护 |
现代支持情况 | mysql 8.0 移除 | postgresql 官方推荐扩展 |
推荐替代方案 | redis 缓存 + innodb buffer pool | 使用 shared_buffers + pg_prewarm |
实战建议
若你是运维/postgresql dba
建议使用 pg_prewarm
结合 pg_buffercache
、监控热页访问模式,定期导出热数据页信息,并写入 cron 脚本,在系统重启后调用预热脚本提升性能。
若你还在使用老版本 mysql(5.6/5.7)
避免启用 query cache(除非是非常小的读密集型场景),建议通过应用层缓存 + innodb 参数优化提升查询效率。
- 使用 innodb 缓冲池预热:
innodb_buffer_pool_dump_at_shutdown = 1 innodb_buffer_pool_load_at_startup = 1
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论