Query Cache的陷阱

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
全局流量管理 GTM,标准版 1个月
简介: 事情背景: 公司在使用MySQL作为线上业务的生产库,某一天,同事说,怪不得select有时候很慢,原来查询缓存(Query Cache)没有打开,昨晚找了个空闲时间就打开了~ 发现问题: 在例行检查status的时候,想起了Qcache的事情,因为...

事情背景:
公司在使用MySQL作为线上业务的生产库,某一天,同事说,怪不得select有时候很慢,原来查询缓存(Query Cache)没有打开,昨晚找了个空闲时间就打开了~

发现问题:
在例行检查status的时候,想起了Qcache的事情,因为以前都是关着的,所以各项统计都是0,正好同事打开了Qcache,就打算去看看Qcache的运行状况
然而结果真是亮瞎了
注:测试使用的MySQL 5.7.7-rc,文档采用的是MySQL 5.6 不要问我为什么文档和数据库版本不一致,真是懒得下5.7的了 _(:з」∠)_ 

简单的翻了一下MySQL的官方文档,看了一些这几行数据代表的意义,

Qcache_free_blocks : QueryCache中的空闲块
Qcache_lowmem_prunes : 当QueryCache的空间不够用时,从QueryCache移除的查询缓存结果数
Qcache_not_cached : 没用到缓存的查询数(无法被缓存,或者是依据MySQL的设置不被缓存的查询)
Qcache_queries_in_cache : 注册进QueryCache的查询数(其实就是当前保存的查询结果数,一个结果对应一个“注册”的SQL语句,后文有验证)
Qcache_hits : 缓存命中数
Qcache_inserts  : 向QueryCache中添加缓存结果的次数

很明显能看出,hits/inserts<0.1,这说明有大量的查询结果写进了QueryCache,但是实际上缓存的利用率确非常低,只有10%不到的结果再次被使用,效果突出一个惨
not_cached>>>>>>queries_in_cache,这说明运行在这个库的业务SQL语句,绝大多数都没有放进缓存里面or绝大多数没有理用到缓存
Qcache_lowmem_prunes的数据说明当前的QueryCache的大小还可以增加一点,防止缓存的结果被刷出去
在10%都不到的利用率面前,初步判断QueryCache的大小并不是主要问题......

寻找原因:继续在官方文档里面找有关QueryCache的资料,发现如下描述



直译过来:只有当查询的TEXT完全一致(byte级别的一致),才会利用查询缓存,这意味着大小写的不同,SQL语句内部的空格数,制表符,参数等地方的不一致都会导致无法使用QueryCache,官方也举了一个不能使用QueryCache的例子。
            
之所以用TEXT来描述SQL语句,是因为如下描述



直译过来:查询的语句以TEXT的格式保存在QueryCache里面,并且占位符?已经被实际的参数所取代,一个具体的SQL语句对应一个具体的结果集(验证结果在最后,直接贴结论)。
直白一点的理解,这个QueryCache以一种类似于Key-Value的形式,把查询语句的TEXT作为key,实际执行结果作为Value保存起来

QueryCache的实现策略相对比较简单粗暴,并没有去“智能”的多缓存一些最近查询结果相邻的一些额外数据。
而且最重要的,任何改变了表,或者表数据的操作,都会使得这个表相关的所有缓存全部失效!
官方文档列举了一些例子,懒,不翻译了......如下图
    


那么,显而易见,MySQL提供的这个QueryCache并不算是一个很实用的东西,所以推荐同事找个时间把这个东西给关闭,使得数据库层面进行查询的时候,减少一个查询QueryCache的步骤,提升高并发,大访问量下的数据库效率。
关闭的方法很多,网上可以搜索到

思考:
看上去这个东西这么坑爹,为什么Oracle还要加入这个特性?看看官方的解释,感觉挺苍白的,大致意思就是最多提高13%的查询消耗,但是能最多提升238%的查询性能。
从写学术论文的角度来看,这个文字游戏也是玩的溜,不过关于这个QueryCache,官方文档还提到了另外一点,


如红字标出:如果查询缓存能够命中,那么Server会跳过SQL解析和SQL执行这两个阶段,直接返回缓存的结果
这意味着,这个QueryCache是处于SQL解析之前的一层判断逻辑
相比较于Oracle,Oracle至少也要在PGA里面解析了SQL,再去SGA取数据,即便是都走的缓存,在逻辑操作上面,MySQL的QueryCache是“更少”的。
所以虽然现在QueryCache不好用,不实用,不过在将来,官方/第三方也许能开发出一套足够高效的算法来改善QueryCache的缓存策略,从而能达到“不解析也能得出结果”的目标。

-------------------------------------------------------------------------------------------验证-----------------------------------------------------------------------------------------------
SQL用的占位符?是被替换成实际参数再保存在QueryCache里面的么?
来验证一下:
1.重启数据库,开启QueryCache

2.查看Qcache的统计数量

上来就是2,其实是执行了use和show status like 'Qcache%',没想到这种语句也会计算进去╮(╯_╰)╭

3.正戏开始,先执行一个select语句,然后再执行一次,看看计数器的变化

可以看到,第一次查询在QueryCache中找不到,所以insert了进去,之后再执行一模一样的查询

可以看到查询缓存命中了,hits数+1,那么假设前端使用的?占位符替代的10000,当?代表的值变换之后,结果如何?

可以看到查询条件的值变换之后,QueryCache再次出现了miss,把新结果放进了QueryCache
然后reset query cache,顺便看一下Qcache_queries_in_cache的意义

显而易见,这个属性代表放在QueryCache中的查询结果数
----------------------------------------------------------------------------------------The End--------------------------------------------------------------------------------------------

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5月前
|
存储 缓存 关系型数据库
MySQL数据库缓存query_cache 19
【7月更文挑战第19天】MySQL数据库缓存query_cache
178 73
|
XML SQL Java
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
|
SQL 关系型数据库 PostgreSQL
PostgreSQL 统计信息混淆之处(scan,read,fetch,hit)源码解读
PostgreSQL 几个统计信息的解释难以理解,所以本文花一些时间从源码的角度来解释一下。 让大家对这几个容易误解的统计值有更好的理解。 比较难理解的几个统计值为: pg_stat_all_indexes 的 ``` idx_scan idx_tup_read idx_tup_fetch ``` pg_statio_all_indexes 的 ``` idx_blks_read idx_blks_hit ``` pg_stat_all_tables 的 ``` seq_scan seq_tup_read idx_
4451 0
|
机器学习/深度学习 SQL 关系型数据库
|
SQL Oracle 关系型数据库
【MOS】常见问题cursor library cache类型的等待事件
【MOS】常见问题:'cursor:mutex ..'/ 'cursor:pin ..'/ 'library cache:mutex ..'类型的等待事件 (文档 ID 1525791.
1059 0
|
Oracle 关系型数据库 MySQL
|
安全 数据库
memory_limit session.cache_expire ecshop初始化注释说明
memory_limit session.cache_expire ecshop初始化注释说明 memory_limit = 128M; 一个脚本所能够申请到的最大内存字节数(可以使用K和M作为单位)。
956 0