数据库查询缓存 Query Cache 的设置、缓存命中率、原理和局限性

2022-05-05 19:20:48

查询缓存 Query Cache 是什么,有什么局限,从设置查询缓存应对爬虫压力到解释 MySQL 8.0 为什么取消了查询缓存

1. 为什么使用查询缓存?

某网站的爬虫频次日统计折线图

如图是近期,笔者维护的某站点的爬虫频次日统计折线图。加上其所在集群节点的其它站点的爬虫频次,每日负载的爬取请求数量大概在 10 万左右,请求特点:

1. 查询请求

2. 每次爬取时间很短,瞬时查询频次高

3. 查询语句存在大量重复


解决方案

开启查询缓存,在 my.ini 加入:

query_cache_size=128M // 查询缓存大小,1024 倍数
query_cache_type=1 //缓存所有 SELECT,除非主动声明 SQL_NO_CACHE

开启后,使用下面的 SQL 语句查询各配置项:

show variables like '%query_cache%';

开启后,比较一段时间前后,使用下面的 SQL 语句的缓存命中效果:

show status like '%Qcache%';


查询缓存 Query Cache 优点:

1. MySQL 自己管理的内存实现:哈希表 查询 + 数据通过链表将 block 相连。节省资源,少磁盘 I/O,少系统调用

2. 无需经过 Optimizer 和存储引擎:快!


查询缓存 Query Cache 缓存规则及局限性:

1. SQL 语句生成哈希值,严格匹配结果:命中率低,有冗余,SQL 语句稍有不同,即不命中。不同 SQL,结果相同,缓存冗余

2. 数据表的结构或数据变化,该表缓存失效:失效率高,全局锁,依赖全局锁保护,缓存越大,耗时越长

3. 使用 函数(值实时变化)、结果超过 query_cache_limit,分区分表,触发器、存储过程、存储函数,不缓存:无效

4. 数据小于 query_cache_min_res_unit,也要占用一个数据块:并行时,容易产生内部内存碎片。需要频繁清理内存


MySQL 取消查询缓存

1. 缓存命中率是评估缓存的重要指标,但查询缓存 Query Cache 由于局限性,缓存命中率业务场景高度耦合,并且不可预测

2. 考虑一般场景,特别是并发时,事务的处理速度,查询缓存为 0 最高

开启和关闭数据库查询缓存 Query Cache 时,事务的处理速度跟随并发进程数量增长的变化折线图

3. 客户端、中间层缓存,不需要数据库服务器生成哈希、建立缓存、管理内存、处理互斥锁。通过内存键名和值存储,实现简单,性能更优

已数据库中间层缓存的实现 ProxySQL 为例,对比使用 MySQL 查询缓存的基准测试柱状图