icewing

MySQL要不要开启查询缓存(Query Cache)&作用
之前在调整网站的时候遇到过QC(Query Cache),大致了解了一下,当时得出的结果是对于只读网站很适合开启,...
扫描右侧二维码阅读全文
30
2018/10

MySQL要不要开启查询缓存(Query Cache)&作用

之前在调整网站的时候遇到过QC(Query Cache),大致了解了一下,当时得出的结果是对于只读网站很适合开启,所以直接跳过了。没有比较深入的了解,这次又遇到了来细致学习一下。

结论

关于标题问题的结论,这里先做一个解答:对于有较多更新数据操作的网站,建议不要开启。
举例的话我目前能想到的就是博客了,对于博客来说(这里指的是个人博客)一般更新都是缓慢的。数据表比较稳定,这时候给博客开启QC效果可能会比较显著(本博客并没有开启QC)。但是据我了解来看它的作用也是比较微小的,如果应用层能够实现缓存,QC开不开都没有多大关系。因为使用它的时候会消耗系统开销,如果数据库一共往QC中写入了约800W次缓存,但是实际命中的只有约500W次。也就是说,每一个缓存的使用率约为0.66次。很难说,该缓存的作用是否大于QC系统所带来的开销。

介绍

当你的数据库打开了QC功能后,数据库在执行SELECT语句时,会将其结果放到QC中,当下一次处理同样的SELECT请求时,数据库就会从QC取得结果,而不需要去数据表中查询。有测试表明在极端情况下可以提高效率238%,但实际情况QC是一个适用较少情况的缓存机制,出现率比较低。

从我查询的来看,Query Cache有如下规则,如果数据表被更改,那么和这个数据表相关的全部Cache全部都会无效,并删除之。这里“数据表更改”包括: INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE等

举个例子,如果数据表posts访问频繁,那么意味着它的很多数据会被QC缓存起来,但是每一次posts数据表的更新,无论更新是不是影响到了cache的数据,都会将全部和posts表相关的cache清除。如果你的数据表更新频繁的话,那么Query Cache将会成为系统的负担。有实验表明,糟糕时,QC会降低系统13%的处理能力。

优劣

根据MySQL官方的测试,QC的优劣分别是:

  • 如果对一个表执行简单的查询,但每次查询都不一样的话,打开QC后,性能反而下降了13%左右。但通常实际业务中,通常不会只有这种请求,因此实际影响应该比这个小一些。
  • 如果对一个只有一行数据的表进行查询,则可以提升238%,这个效果还是非常不错的。

注:QC严格要求2次SQL请求要完全一样,包括SQL语句,连接的数据库、协议版本、字符集等因素都会影响。

下面几个例子中的SQL语句,在开启QC后会被认为是完全不一样的不会使用同一个QC内存块:

set names latin1; SELECT * FROM table_name;
set names latin1; select * from table_name;
set names utf8; select * from table_name;

成本

在MySQL里QC是由一个全局锁在控制,每次更新QC的内存块都需要进行锁定。

例如,一次查询结果是20KB,当前 query_cache_min_res_unit 值设置为 4KB(默认值就是4KB,可调整),那么么本次查询结果共需要分为5次写入QC,每次都要锁定,可见其成本有多高。

参数

下面是关于Query Cache相关参数

query_cache_size:设置Query Cache所使用的内存大小,默认值为0,大小必须是1024的整数倍,如果不是整数倍,MySQL会自动调整降低最小量以达到1024的倍数。

query_cache_type:控制Query Cache功能的开关,可以设置为0(OFF),1(ON)和2(DEMAND)三种:0表示关闭Query Cache功能,任何情况下都不会使用Query Cache;1表示开启Query Cache功能,但是当SELECT语句中使用的SQL_NO_CACHE提示后,将不使用Query Cache;2(DEMAND)表示开启Query Cache功能,但是只有当SELECT语句中使用了SQL_CACHE提示后,才使用Query Cache。

query_cache_limit:允许Cache的单条Query结果集的最大容量,默认是1MB,超过此参数设置的Query结果集将不会被Cache。

query_cache_min_res_unit:设置Query Cache中每次分配内存的最小空间大小,也就是每个Query的Cache最小占用的内存空间大小。

query_alloc_block_size:缓存的块大小,默认为8192字节。

query_cache_wlock_invalidate:控制当有写锁加在表上的时候,是否先让该表相关的Query Cache失效,1(TRUE),在写锁定的同时将使该表相关的所有Query Cache 失效。0(FALSE),在锁定时刻仍然允许读取该表相关的Query Cache。

Qcache_lowmem_prunes:这是一个状态变量(show status),当缓存空间不够需要释放旧的缓存时,该值会自增。

Qcache_free_blocks:目前还处于空闲状态的Query Cache中内存Block数目。

Qcache_free_memory:目前还处于空闲状态的Query Cache内存总量。

Qcache_hits:Query Cache命中次数。

Qcache_inserts:向Query Cache中插入新的Query Cache的次数,也就是没有命中的次数。

Qcache_lowmem_prunes:当Query Cache内存容量不够,需要从中删除老的Query Cache以给新的Cache对象使用的次数。

Qcache_not_cached:没有被Cache的SQL数,包括无法被Cache的SQL以及由于query_cache_type设置的不会被Cache 的 SQL。

Qcache_queries_in_cache:目前在Query Cache中的SQL数量。

Qcache_total_blocks:Query Cache中总的Block数量。

延伸阅读

最后修改:2018 年 10 月 30 日 06 : 07 PM
生活需要一些仪式感,比如手冲一杯咖啡:)

发表评论