MySQL 查询缓存

1.查询缓存提高查询速度

    MySQL 提供了查询缓冲的功能(只能在MySQL4.0.1及以上版本使用查询缓冲),我们可以通过查询缓冲在一定程度上提高查询性能。通过在MySQL安装目录中的my.ini文件设置查询缓冲。设置也非常简单,只需要将query_cache_type设为1即可。在设置了这个属性后,MySQL在执行任何SELECT语句之前,都会在它的缓冲区中查询是否在相同的SELECT语句被执行过,如果有,并且执行结果没有过期,那么就直接取查询结果返回。

    但在写SQL语句时注意,MySQL的查询缓冲是区分大小写的。如下列的两条SELECT语句:

SELECT * from TABLE1;
SELECT * FROM TABLE1;
上面的两条SQL语句对于查询缓冲是完全不同的SELECT,而且查询缓冲并不自动处理空格,因此,在写SQL语句时,应尽量减少空格的使用,尤其是在SQL首和尾的空格(因为,查询缓冲并不自动截取首尾空格)。 

初始环境:

$ mysql.admin ext -i 1 | grep "Qcache_hits" 
| Qcache_hits                       | 0         | 

$ mysql.admin ext -i 1 | grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 0         | 

/* 初始化数据: */
mysql> create table tb_qc(a int,b char(10));  
Query OK, 0 rows affected (0.00 sec) 

mysql> insert into tb_qc values(1,'line1'); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into tb_qc values(2,'line2'); 
Query OK, 1 row affected (0.00 sec)

/* 查看状态值: */
$ mysql.admin ext -i 1 | grep "Qcache_hits" 
| Qcache_hits                       | 0         |  

$ mysql.admin ext -i 1 | grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 0         | 

/* 此时,Qcache_hits=0,Qcache_queries_in_cache=0,没有变化,执行一个查询:*/ 

mysql> select * from tb_qc where a=1; 
+------+-------+ 
| a    | b     | 
+------+-------+ 
|    1 | line1 |  
+------+-------+ 
1 row in set (0.00 sec) 

/* 查看状态值:  */
$ mysql.admin ext -i 1 | grep "Qcache_hits" 
| Qcache_hits                       | 0         | 

$ mysql.admin ext -i 1 | grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 1         |  

/* Qcache_hits=0,没有命中query cache里任何sql(此时qc里面也没有sql); 
 Qcache_queries_in_cache=1,执行过一次后sql就存储在qc里面 
 再执行一次相同的sql,应该可以直接从qc里面取得结果数据,试一下 */

mysql> select * from tb_qc where a=1; 

$ mysql.admin ext -i 1 | grep "Qcache_hits" 
| Qcache_hits                       | 1         |  

$ mysql.admin ext -i 1 | grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 1         | 

/* Qcache_hits=1,说明确实命中了qc中的sql */

/* 再执行一个不同条件的 */
mysql> select * from tb_qc where a=2; 
+------+--------+ 
| a    | b      | 
+------+--------+
|    2 | line2  |  
+------+--------+ 
1 row in set (0.00 sec)  

$ mysql8801.admin ext -i 1 | grep "Qcache_hits" 
| Qcache_hits                       | 1         |  

$ mysql8801.admin ext -i 1 | grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 2         | 

/*Qcache_hits=1,没有命中,因为qc里面只有a=1的sql,没有a=2的; 
但Qcache_queries_in_cache=2,说明新的sql也被cache了,下次执行就可以直接从qc取结果了 */

2.谨慎使用查询缓存

    虽然不设置查询缓冲,有时可能带来性能上的损失,但有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次)。这样就需要把缓冲关了。当然,这可以通过设置query_cache_type的值来关闭查询缓冲,但这就将查询缓冲永久地关闭了。在MySQL 5.0中提供了一种可以临时关闭查询缓冲的方法: 
SELECT SQL_NO_CACHE field1, field2 FROM TABLE1;
以上的SQL语句由于使用了SQL_NO_CACHE,因此,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它。 
我们还可以将my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲,如:
SELECT SQL_CALHE * FROM TABLE1;
此外,官方文档中说,qc里的表不能有任何变动(Insert/Update/Delete/Replace/select .. for update/load data infile/Alter table/Truncate/Drop table/Drop database),否则qc里面的数据就无效,会被清掉。
/*新增一行数据: */
mysql> insert into tab_qc values(3,'SINA'); 
Query OK, 1 row affected (0.00 sec) 

$ mysql8801.admin ext -i 1|grep "Qcache_hits" 
| Qcache_hits                       | 1         | 

$ mysql8801.admin ext -i 1|grep "Qcache_queries_in_cache" 
| Qcache_queries_in_cache           | 0         | 

/* Qcache_queries_in_cache=0,说明qc里面之前缓存的sql结果已经被清掉了,尽管我做的修改与qc里的数据无关*/ 
如果是这样,那QC的使用场景就十分有限了,查询多,但对表的更改很少才能体现出QC的价值。哪怕是一行数据的修改都会导致数据从QC从中清除。
    如果表上写比较频繁,那么使用QC反而是一种负担,mysql不停的将数据读入QC,很快又把所有数据删除。
    另外,表上有锁,包括表锁和行锁,其他事务都不能访问query cache。
    所以说,查询缓存(query cache),并没有想的那么好。 还是尽量在应用端使用缓存,还好目前缓存的产品有很多可供我们选择,比如memcached(key-value),redis(key-value,list)等。
    官方文档上有写:最坏情况下,查询缓存的激活率是13%,最好情况查询缓存可以提高238%效率。

附:

Qcache_hits,是指query命中查询缓存的次数,它是递增的
Qcache_queries_in_cache,是指当前查询缓存中已经cache的sql结果的个数
注意:命中QC的query,Qcache_hits加1,但Com_select不增加
有关query cache的其他一些参数:
mysql> SHOW VARIABLES LIKE 'have_query_cache';  ##QC是否可用
mysql> SHOW VARIABLES LIKE 'query_cache_size';   ##QC大小,可动态设置
mysql> SHOW VARIABLES LIKE 'query_cache_type';  ##
0或OFF将阻止缓存或查询缓存结果。
1或ON将允许缓存,以SELECT SQL_NO_CACHE开始的查询语句除外。
2或DEMAND,仅对以SELECT SQL_CACHE开始的那些查询语句启用缓存。
mysql> SHOW VARIABLES LIKE 'query_cache_min_res_unit';  ###
为了减少QC内存碎片,系统最小分配的大小
如果结果集都很小,则该值可以设置很小
如果结果集都很大,则该值可以设置大些
参考状态值Qcache_free_blocks和Qcache_lowmem_prunes

你可能感兴趣的:(mysql,查询缓存)