MySQL 查询缓存

今天说一说MySQL的查询缓存。查询缓存嘛,顾名思义就是提高查询性能用的,检索的时候不用去磁盘找了,直接把之前的缓存结果拿出来就返回了。


下面咱们讨论一下MySQL查询缓存的细节:


首先既然是查询缓存,那就只对SELECT语句起作用,这貌似是一句废话,但确实是如此。下面咱说的貌似不是废话的,查询缓存的结果是可以被会话共享的,也就是说同样的查询语句缓存,一个客户端刚查过的结果,另外一个客户端再查询是可以直接用这个缓存结果的。看起来很爽对不对,但是缓存真正应用起来还是有很多限制和使用场景要求的。


首先是缓存适合于那些不太经常修改的数据,原因很明显,缓存并不会造成读出陈旧数据,所以一旦数据被修改,缓存就作废了。对应频繁修改的表,缓存并不合适。倒是比较适合单行数据的缓存,尽管表本身经常有新数据插入,只要旧数据修改不频繁就不怕了。


第二点,对应SELECT语句中包含了函数的,缓存也无法应用,因为函数的值是不可控的,例如:CURDATE()获取当前日期 、RAND()取随机数等等都无法应用缓存。


第三点,缓存是对查询语句的精确匹配,也就是说只有查询语句有一点点不一样,都不能使用到之前的缓存。注意是一点点不一样都不行,包括大小写。也就是说, select * from t1  和 SELECT * FROM t1 这两个语句无法使用同一个缓存。


第四点,下列情况都无法应用查询缓存:

1) 用户定义函数或存储过程无法应用查询缓存;

2)用户变量或者局部存储程序变量无法应用查询缓存;

3)系统表都无法应用查询缓存: mysql库、INFORMATION_SCHEMA库,或者performace_schema库   (这点影响不大)

4)在MySQL 5.6.5及后续版本中分区表都无法应用查询缓存;

5) 以下格式语句的都无法应用查询缓存:

      SELECT  .......  LOCK IN SHARE MODE

      SELECT ......... FOR UPDATE

      SELECT ........  INTO OUTFILE ...

      SELECT .......    INTO DUMPFILE .....

      SELECT * FROM ... WHERE autoincrement_col IS NULL

6)  使用临时表的无法应用查询缓存;

7)没使用任何表的无法应用查询缓存;(这基本是废话)

8)语句产生警告的无法应用查询缓存;


大家看了以后是不是有些崩溃了,如此多的限制,貌似没啥可玩的了。大概也就我开始的那些场景比较适合应用了。不管怎么样,现在我们来看看如果设置缓存吧。


设置之前,先看看缓存开启了没有,执行语句:


SHOW VARIABLES LIKE 'have_query_cache'


mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
YES就代表是开启了。


设置缓存的大小, 通过设置系统变量  query_cahe_size来设置缓存的大小,如果设置为0则等于不应用缓存,也可以通过设置系统变量  query_cache_type=0,效果是一样的。默认情况下,查询缓存是关闭的。默认情况下,缓存大小为1M。如果设置的太小是会产生警告的,所以应该设置的大一点,所谓大1M就算是大了。 设置的时候要注意单位是byte。

除了设置全局系统变量,也可以通过设置客户端SESSION实现仅当前客户端禁用缓存 

mysql> SET SESSION query_cache_type = OFF;

在开启的情况下,我们也可以强制我们想要的语句不进行缓存,可以使用  SQL_NO_CACHE选项, 例如: SELECT SQL_NO_CACHE id ,name FROM customer,那么这个查询客户表的语句就不会被缓存啦。



当结果被缓存的时候,不是在一个大的块中。而是按需要被存储在许多小块中,一个块被填满了,才会分配另一个新的块。因此内存分配也会花费很多的时间,所以合理的块大小就很重要。系统变量  query_cache_min_res_unit就是设置这个块大小的。默认情况下,这个值是4K,这个默认值可以适应绝大多数情况了。但是如果你有很多非常小的查询结果集,或者大部分查询结果集都非常大,就应该适当调整这个参数。


最后说说如何查看缓存的效果,现在缓存已经应用了,如果看效果呢? 执行语句  SHOW STATUS LIKE 'Qcache%' 查看

mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+--------+
| Variable_name           | Value  |
+-------------------------+--------+
| Qcache_free_blocks      | 36     |
| Qcache_free_memory      | 138488 |
| Qcache_hits             | 79570  |
| Qcache_inserts          | 27087  |
| Qcache_lowmem_prunes    | 3114   |
| Qcache_not_cached       | 22989  |
| Qcache_queries_in_cache | 415    |
| Qcache_total_blocks     | 912    |
+-------------------------+--------+

大家可以看到缓存hits命中数等等关心的数据。


再补充一点缓存维护的吧:


1)缓存时间长了,容易产生碎片,可以通过 FLUSH QUERY CACHE语句来清除碎片,清除碎片并不会将缓存结果本身清除掉。

2)那要清除缓存结果怎么办呢? 可以使用  RESET QUERY CACHE  清除缓存结果。执行 FLUSH TABLES语句可以带来同样的效果。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值