Mysql

关于MySQL的QC(QueryCache)的学习笔记

2016-10-09  本文已影响0人  Alex_Paul

Query Cache (查询缓存, 以下简称QC), 查询SELECT语句记起产生的数据结果, 如果以后遇到相同的语句时(语句完全一样) 服务器从会返回查询缓存的结果, 而不是分析数据表. QC适用于一些静态页面, 或者页面不经常更新的信息。
由于QC需要缓存最新数据结果, 所以当表中数据有变化时(INSERT,UPDATE,DELETE或者其他可能产生数据变化的操作),都会导致QC被刷新。
查看QC:

SHOW STATUS LIKE 'Qcache%';

查询结果:

Variable_name Value
Qcache_free_blocks 2577
Qcache_free_memory 8904480
Qcache_hits 1548269
Qcache_inserts 1287698
Qcache_lowmem_prunes 86872
Qcache_not_cached 884767
Qcache_queries_in_cache 6315
Qcache_total_blocks 15213
  • Qcache_free_blocks: 当一个表被更新之后, 和它相关的cache blocks将被free。 但是这个block依然可能存在队列中, 除非是在队列的尾部。这些blocks将被统计到这个值来, 可以用FLUSH QUERY CACHE语句来清空free blocks。
  • Qcache_free_memory:可用内存, 如果很小, 考虑增加query——cache_size。
  • Qcache_hits:自mysql进程启动起,cache的命中数量。
  • Qcache_inserts:自mysql进程启动起, 被增加进QC的数量。
  • Qcache_lowmem_prunes:由于内存过少而导致QC被删除的条数。加大query_cache_size,尽可能保持这个值0增长。
  • Qcache_not_cached:自mysql进程启动起,没有被cache的只读查询数量(包括select,show,use,desc等)。
  • Qcache_queries_in_cache:当前被cache的SQL数量。
  • Qcache_total_blocks:在QC中的blocks数。一个query可能被多个blocks存储,而这几个blocks中的最后一个,未用满的内存将会被释放掉。例如一个QC结果要占6KB内存,如果query_cache_min_res_unit是4KB,则最后将会生成3个blocks,第一个block用来存储sql语句文本,这个不会被统计到query+cache_size里,第二个block为4KB,第三个block为2KB(先allocate4KB,然后释放多余的2KB)。每个表,当第一个和它有关的SQL查询被CACHE的时候,会使用一个block来存储表信息。也就是说,block会被用在三处地方:表信息,SQL文本,查询结果。

在一个更新频率非常低而且只读查询频率非常高的场景下,打开QC还是比较有优势的,其他场景下, 则不建议使用,因为起大多只会增加查询负担,而不会增加查询效率,而且,QC一般维持在100M以内就足够了。

而且QC也不适用于下面几个场景:
1、子查询或者外层查询;
2、存储过程、存储函数、触发器、event中调用的SQL,或者引用到这些结果的;
3、包含一些特殊函数时,例如:BENCHMARK()、CURDATE()、CURRENT_TIMESTAMP()、NOW()、RAND()、UUID()等等;
4、读取mysql、INFORMATION_SCHEMA、performance_schema 库数据的;
5、类似SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE、SELECT..INTO OUTFILE/DUMPFILE、SELECT..WHRE…IS NULL等语句;
6、SELECT执行计划用到临时表(TEMPORARY TABLE);
7、未引用任何表的查询,例如 SELECT 1+1 这种;
8、产生了 warnings 的查询;
9、SELECT语句里加了 SQL_NO_CACHE 关键字;

而且,MySQL在从QC中取回结果钱, 会先判断执行SQL的用户是否有全部库,表的SELECT权限, 如果没有,也不会使用QC。
最重要的一点是,在MySQL里QC是由一个全局的锁在控制, 每次更新QC的内存块都需要进行锁定。
例如,一次查询的结果是20KB,当前query_cache_min_res_unit 值设置为 4KB(默认值就是4KB,可调整),那么么本次查询结果共需要分为5次写入QC,每次都要锁定,可见其成本有多高。

总结就是:

如果线上99%以上都是只读,几乎无更新,那么可以考虑开启QC,否则,就别开了(默认是开启的)

关闭方法:

  • 1.同时设置选项 query_cache_type = 0 和 query_cache_size = 0;
  • 2.如果用源码编译MySQL的话,编译时增加参数 --without-query-cache 即可;
python技术交流群: 577128300
上一篇下一篇

猜你喜欢

热点阅读