MYSQL Query-cache使用方法及注意事项

mysql有三种cache,tablecache,threadcache 和querycache
。今天了解下querycache


mysql的querycache,故名思议,就是存储select query相关数据
就是将selecet语句和result做hash映射,保存在内存区域中。


1、具体预览 SHOW GLOBAL STATUS


SHOW GLOBAL STATUS LIKE '%Qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 2        | 处于空闲状态的querycache中内存block数目
| Qcache_free_memory      | 62834600 |处于空闲状态querycache内存总量
| Qcache_hits             | 7        |qc命中率
| Qcache_inserts          | 42       |像qc中插入新的qc次数,或者理解没有命中的次数
| Qcache_lowmem_prunes    | 0        |当2的内存数量不够时,需要从qc中删除旧的给新的qc腾地的次数
| Qcache_not_cached       | 35       |没有被cache的sql数量,也包括由于querycahcetype设置导致出现
| Qcache_queries_in_cache | 7        |目前在qc中的sql数量
| Qcache_total_blocks     | 30       |目前在qc中总的block数量。
+-------------------------+----------+
8 rows in set


注意,只有selecet会被querycache缓存,其他insert delete show等都不会。也包括存储过程的select也不会。如果一个表被更新,那么和这个表相关的SQL的所有QC都会被失效。假设一个联合查询里涉及到了表A和表B,如果表A或者表B的其中一个被更新(update或者


delete),这个查询的QC将会失效。
查询中有一些不确定的数据时,也是不会缓存的,比方说now(),current_date(),自定义函数,存储函数,用户变量,字查询等。所以这样的查询也就不会命中缓存,但是还会去检测缓存的,因为查询缓存在解析SQL之前,所以MySQL并不知道查询中是否包含该类函数,只


是不缓存,自然不会命中。 


所以看出来qc缓存其实没多大作用了,但是如果你任性,内存大,pv高,那用把!


show variables like 'query_cache%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_cache_limit            | 1048576 |如果查询结果大于这个值,不缓存
| query_cache_min_res_unit     | 4096    |每次给QC结果分配内存的大小
| query_cache_size             | 0       |分 配给QC的内存。如果设为0,则相当于禁用QC。QC存储的最 小单位是1024 byte
| query_cache_type             | ON      |0 完全禁止QC,不受SQL语句控制(另外可能要注意的是,即使这里禁用,上面一个参数所设定的内存大小还是会被分配);1启用QC,可以在SQL语句使用SQL_NO_CACHE禁用;2可以在SQL语句使用SQL_CACHE启用。
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+


SHOW GLOBAL STATUS LIKE '%Com_select%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select    | 80    |
+---------------+-------+
1 row in set
mysql> SHOW STATUS LIKE 'Qcache%'; 
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| Qcache_free_blocks      | 0     |
| Qcache_free_memory      | 0     |
| Qcache_hits             | 0     |
| Qcache_inserts          | 0     |
| Qcache_lowmem_prunes    | 0     |
| Qcache_not_cached       | 0     |
| Qcache_queries_in_cache | 0     |
| Qcache_total_blocks     | 0     |
+-------------------------+-------+
8 rows in set


开启的话这样:


my.ini中,设置 
     query_cache_size=128M 
   增加一行:query_cache_type=1 
还有一个query_cache_limit 2M


HIT RATE= Qcache_queries_in_cache/Com_select
如果数据频繁更新,那么cache就基本没用了,反而增加内存负担。


另外:借鉴前辈之路,如果一定时期内达不到85%以上的,基本就会起到反作用。毕竟默认也是关闭的。
eg:
再如,一个更新频繁的BBS系统。下面是一个实际运行的论坛数据库的状态参数:


QCache_hit 5280438
QCache_insert 8008948
Qcache_not_cache 95372
Com select 8104159
可以看到,数据库一共往QC中写入了约800W次缓存,但是实际命中的只有约500W次。也就是说,每一个缓存的使用率约为0.66次。很难说,该 缓存的作用是否大于QC系统所带来的开销。但是有一点是很肯定的,QC缓存的作用是很微小的,如果应用层能够实现缓存,将可


以忽略QC的效果。


打开Qcache对读和写都会带来额外的消耗: 
a、读查询开始之前必须检查是否命中缓存。 
b、如果读查询可以缓存,那么执行完之后会写入缓存。 
c、当向某个表写入数据的时候,必须将这个表所有的缓存设置为失效,如果缓存空间很大,则消耗也会很大,可能使系统僵死一段时间,因为这个操作是靠全局锁操作来保护的。 
对InnoDB表,当修改一个表时,设置了缓存失效,但是多版本特性会暂时将这修改对其他事务屏蔽,在这个事务提交之前,所有查询都无法使用缓存,直到这个事务被提交,所以长时间的事务,会大大降低查询缓存的命中 
    
   一个表可以被许多类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。 
对于InnoDB而言,事物的一些特性还会限制查询缓存的使用。当在事物A中修改了B表时,因为在事物提交之前,对B表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事物A提交之前是不可缓存的。如果A


事物长时间运行,会严重影响查询缓存的命中率 


查询缓存的空间不要设置的太大。 
因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况 


关于mysql的全局变量
show variables like '%%'
select @@query_cache_size;
SHOW GLOBAL STATUS LIKE '%%'
SET GLOBAL query_cache_size = 31457280;
SET @@global.query_cache_size = 20971520;
show processlist
show status


另外问答:参考
(jackyrong.iteye.com/blog/2173523)
相关问答: 
Query Cache 如何处理子查询的? 
这是我遇到的最为常见的一个问题。其实 Query Cache 是以客户端请求提交的 Query 为对象来处理的,只要客户端请求的是一个 Query,无论这个 Query 是一个简单的单表查询还是多表 Join,亦或者是带有子查询的复杂 SQL,都被当作成一个 Query,不会被分拆成


多个 Query 来进行 Cache。所以,存在子查询的复杂 Query 也只会产生一个Cache对象,子查询不会产生单独的Cache内容。UNION[ALL] 类型的语句也同样如此。 


Query Cache 是以 block 的方式存储的数据块吗? 
不是,Query Cache 中缓存的内容仅仅只包含该 Query 所需要的结果数据,是结果集。当然,并不仅仅只是结果数据,还包含与该结果相关的其他信息,比如产生该 Cache 的客户端连接的字符集,数据的字符集,客户端连接的 Default Database等。 


Query Cache 为什么效率会非常高,即使所有数据都可以 Cache 进内存的情况下,有些时候也不如使用 Query Cache 的效率高? 
Query Cache 的查找,是在 MySQL 接受到客户端请求后在对 Query 进行权限验证之后,SQL 解析之前。也就是说,当 MySQL 接受到客户端的SQL后,仅仅只需要对其进行相应的权限验证后就会通过 Query Cache 来查找结果,甚至都不需要经过 Optimizer 模块进行执


行计划的分析优化,更不许要发生任何存储引擎的交互,减少了大量的磁盘 IO 和 CPU 运算,所以效率非常高。 


客户端提交的 SQL 语句大小写对 Query Cache 有影响吗? 
有,由于 Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以必须要整个 SQL 语句在字符级别完全一致,才能在 Query Cache 中命中,即使多一个空格也不行。 


一个 SQL 语句在 Query Cache 中的内容,在什么情况下会失效? 
为了保证 Query Cache 中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增,修改,删除等,都会使所有引用到该表的 SQL 的 Query Cache 失效。 


为什么我的系统在开启了 Query Cache 之后整体性能反而下降了? 
当开启了 Query Cache 之后,尤其是当我们的 query_cache_type 参数设置为 1 以后,MySQL 会对每个 SELECT 语句都进行 Query Cache 查找,查找操作虽然比较简单,但仍然也是要消耗一些 CPU 运算资源的。而由于 Query Cache 的失效机制的特性,可能由于表上


的数据变化比较频繁,大量的 Query Cache 频繁的被失效,所以 Query Cache 的命中率就可能比较低下。所以有些场景下,Query Cache 不仅不能提高效率,反而可能造成负面影响。 


如何确认一个系统的 Query Cache 的运行是否健康,命中率如何,设置量是否足够? 
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下: 


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 数量 
可以根据这几个状态计算出 Cache 命中率,计算出 Query Cache 大小设置是否足够,总的来说,我个人不建议将 Query Cache 的大小设置超过256MB,这也是业界比较常用的做法。 


MySQL Cluster 是否可以使用 Query Cache? 
其实在我们的生产环境中也没有使用 MySQL Cluster,所以我也没有在 MySQL Cluster 环境中使用 Query Cache 的实际经验,只是 MySQL 文档中说明确实可以在 MySQL Cluster 中使用 Query Cache。从 MySQL Cluster 的原理来分析,也觉得应该可以使用,毕竟 SQL 


节点和数据节点比较独立,各司其职,只是 Cache 的失效机制会要稍微复杂一点。
最常用工具mysqlreport
慢查询分析工具 mysqlsla







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值