文章目录

  • 1、Query Cache简介
  • 2、Query Cache运行原理
  • 3、Query Cache的设置和操作
  • 4、缓存错失(cache miss)
  • 4.1、缓存错失(cache miss)的定义
  • 4.2、缓存错失的原因
  • 5、Query Cache效率的判断方法
  • 6、Query Cache的使用要点
  • 7、总结


1、Query Cache简介

MySQL Query Cache内缓存了所提交的SQL语句的结果集及相关信息,有助于加速查询响应。一般不需要考虑Query Cache带来的额外开销,除非是写操作很频繁的应用。

2、Query Cache运行原理

  1. 当MySQL运行查询语句时,首先会检查是否命中缓存,如果命中那么会增加Qcache_hits状态变量的值,并从缓存区取得结果集返回给客户端。如果没有命中缓存,则继续如下步骤。
  2. 解析器分解查询语句从而建立一棵“解析树”,验证查询语句的语法是否正确。
  3. 预处理器检查“解析树”中的表和列是否存在,列的别名是否混淆,并进行相关权限的检查。
  4. 优化器对“解析树”进行优化,生成执行成本最低的执行计划。
  5. 执行此计划,存储查询结果到缓存。
  6. 返回结果集给客户端。

3、Query Cache的设置和操作

  • Query Cache默认是关闭的,禁用Query Cache的办法是设置query_cache_size为0。
  • 清空缓存:RESET QUERY CACHE命令会将当前所有缓存清空,但FLUSH QUERY CACHE命令并不会清空缓存。
  • 查看缓存配置参数:mysql>show variables like'%query_cache%';
  • 查看缓存状态:mysql>show global status like'%Qcache%';

4、缓存错失(cache miss)

4.1、缓存错失(cache miss)的定义

任何不是从缓存中取得数据的查询语句都称为“缓存错失(cache miss)”,

4.2、缓存错失的原因

造成缓存错失的原因有以下几种。

  • 语句无法缓存:有些查询语句是不可缓存的,主要有两种,一是语句包含了不确定的值,二是结果集太大而无法保存到缓存。这两种原因造成的结果都会增加Qcache_not_cached变量的值;
  • 新的查询语句:所发送的查询语句之前没有发送过。
  • 缓存已被释放:所发送的查询语句的结果集之前是缓存过的,但由于内存不足,MySQL不得不将之前的一些缓存清除掉,以腾出空间来放置其他新的缓存结果。
  • 数据变更导致缓存失效:数据的变更也会引发缓存的失效。如果是数据的变更引起的缓存失效,那么可以通过查看Com_*变量的值来确认有多少查询语句更改了数据,这些变量包括Com_update、Com_delete等。

5、Query Cache效率的判断方法

  1. 衡量Query Cache是否有效的最简单判断方法是缓存命中率,公式为Qcache_hits/(Qcache_hits+Com_select),如果缓冲命中率比较高,那么它就是有效的。一般命中率在98%以上说明Query Cache作用很明显,这种情况下如果Query Cache可能会导致性能下降。
  2. 但即使缓存命中率不高,也不一定意味着低效和一定不需要启用。因为有时候我们关注的可能是提高特定查询的访问速度而不是整体命中率。
  3. 如果一个系统中,大部分都是复杂的查询,那么用Query Cache将是一个很好的选择。

6、Query Cache的使用要点

  • 对写操作很频繁的应用,建议禁用Query Cache:因为只要有一条语句更改了表,哪怕只改了一条数据,MySQL就会让与这个表相关的Query Cache整个都失效掉。这时Query Cache非但没有帮助,反而因为频繁交替的加载和失效操作导致效率下降。
  • 规范性开发有助于Query Cache命中提高:SQL语句在Query Cache中是通过散列映射表来查找的,所以大小写、空格等差异都会导致不同的散列结果,因此开发人员应该有一致的代码规范,以保证SQL语句风格一致。
  • Query Cache不缓存子查询。
  • 长事务会降低Query Cache效率:因为事务内对表的修改会让该表相关的Query Cache失效,直到这个事务提交之后,才可以重新缓存这个表的结果集。
  • Query Cache并不需要等待所有的结果集在Cache内全部生成后才发送给客户端。
  • Query Cache分配内存的时候,每次至少要分配query_cache_min_res_unit大小的内存块,实际上生产环境结果集所需要的Query Cache并不是很大,一般256MB就足够了。
  • 如果Qcache_not_cached比较小,但有大量缓存未命中,那么可能会有很多失效的操作,或者MySQL没有预热数据,或者重复的查询很少。Qcache_inserts在预热数据后,应该比Com_select小得多。

7、总结

  1. MySQL的Query Cache(查询缓存)会将查询结果保存到缓存以提高查询效率,一般情况下查询缓存的开销可以忽略不计,但对于写很频繁的应用,则要考虑查询缓存的开销。
  2. 查询缓存是通过将查询语句做Hash以后保存到缓存中,下次比对两个语句的Hash值从而确认语句是否命中,因此大小写、空格都会影响缓存命中,所以如果希望使用查询缓存,SQL开发尽量要规范。
  3. 所谓缓存错失(cache miss),就是缓存中找不到该语句,一般新的语句、缓存释放、缓存失效都会导致缓存错失。
  4. 查询缓存的效率可以用缓存命中率衡量,公式是Qcache_hits/(Qcache_hits+Com_select),如果命中率高于98%,说明查询缓存比较有效。
  5. 对写操作很频繁的应用,建议禁用Query Cache。因为对于查询缓存来说,只要一个表的一条记录被更新,整个表的查询缓存都会失效。