查询缓存,用于缓存SQL查询语句和该SQL语句对应的结果集。
当MySQL再次接收到相同请求时,会先从查询缓存中检索结果,而不是再次分析和执行这个同样的查询。
从查询缓存中检索结果时,匹配标准是:SQL语句完全相同(区分大小写)。
检查当前MySQL是否支持查询缓存
show variables like ‘have_query_cache’;
说明:
have_query_cache=YES表示当前MySQL支持查询缓存,但并不表示已启用,该变量是只读的,不允许用户修改。
通过set命令修改会报错:ERROR 1238 (HY000): Variable 'have_query_cache' is a read only variable
启用查询缓存
是否启用mysql查询缓存,可以通过2个参数:query_cache_type和query_cache_size,来设置,其中任何一个参数设置为0都意味着关闭查询缓存功能。
在mysql配置文件的[mysqld] 部分,修改如下配置项(没有的话手动添加):
query_cache_size=10M
query_cache_type=1
设置完成后,重启mysql,然后通过show variables like ‘%query_cache%’ 查看:
说明:
(1)query_cache_type有3个值 :
0或off,代表关闭
1或on,代表开启
在on模式下,如果你不想使用缓存,需要通过sql_no_cache关键词来显示的指明,
如select sql_no_cache id,name from tableName;
2 或demand,按需要是否开启缓存。
当sql语句中有SQL_CACHE关键词时才缓存,
如:select SQL_CACHE user_name from users where user_id = '100';
无论哪种模式下,当sql中使用了mysql函数时,都不会缓存。
(2)query_cache_size表示分配给查询缓存的总内存大小,该值并非越大越好,需要结合实际情况设置(此处不做详细说明)。
(3)query_cache_limit 单次查询结果大于这个值,则不再缓存。该值默认是1048576,即1M。
(4)query_cache_min_res_unit 分配的最小缓存块大小,默认是4KB,设置该值大,对大数据查询有好处,但如果你的查询都是小数据 查询,就容易造成内存碎片和浪费。
(5)query_cache_wlock_invaliate 默认为OFF,可以读取已锁定的表的缓存数据
查看缓存情况
其中各个参数的意义如下:
Qcache_free_blocks:表示查询缓存中目前还有多少剩余的blocks,如果该值较大,但是Qcache_lowmem_prunes却不断增加,则说明查询缓存中的碎片过多了。(FLUSH QUERY CACHE会对缓存中的碎片进行整理,从而得到一个空闲块)。
Qcache_free_memory:缓存中的空闲内存。
Qcache_hits:每次查询在缓存中命中时就增大
Qcache_inserts:每次插入一个查询缓存时就增大。
Qcache_lowmem_prunes:缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个 数字在不断增长,就表示可能碎片非常严重,或者内存很少。(上面的 free_blocks和free_memory可以告诉您属于哪种情况)
Qcache_not_cached:不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句或者用了now()之类的函数。
Qcache_queries_in_cache:当前缓存中,缓存(select语句+结果集 对)的数量。
Qcache_total_blocks:缓存中块的数量
关于block块
QC缓存一个查询结果的时候,一般情况下不是一次性地分配足够多的内存来缓存结果的。而是在查询结果获得的过程中,逐块存储。当一个存储块被填满之后,一个新的存储块将会被创建,并分配内存(allocate)。单个存储块的内存分配大小通过query_cache_min_res_unit参数控制,默认为4KB。最后一个存储块,如果不能被全部利用,那么没使用的内存将会被释放。如果被缓存的结果很大,那么会可能会导致分配内存操作太频繁,系统系能也随之下降;而如果被缓存的结果都很小,那么可能会导致内存碎片过多,这些碎片如果太小,就很有可能不能再被分配使用。
除了查询结果需要存储块之外,每个SQL文本也需要一个存储块,而涉及到的表也需要一个存储块(表的存储块是所有线程共享的,每个表只需要一个存储块)。存储块总数量=查询结果数量*2+涉及的数据库表数量。也就是说,第一个缓存生成的时候,至少需要三个存储块:表信息存储块,SQL文本存储块,查询结果存储块。而第二个查询如果用的是同一个表,那么最少只需要两个存储块:SQL文本存储块,查询结果存储块。
通过观察Qcache_queries_in_cache和Qcache_total_blocks可以知道平均每个缓存结果占用的存储块。它们的比例如果接近1:2,则说明当前的query_cache_min_res_unit参数已经足够大了。如果Qcache_total_blocks比Qcache_queries_in_cache多很多,则需要增加query_cache_min_res_unit的大小。
关于查询缓存,mysql官方的说明:
# Query cache is used to cache SELECT results and later return them
# without actual executing the same query once again. Having the query
# cache enabled may result in significant speed improvements, if your
# have a lot of identical queries and rarely changing tables. See the
# "Qcache_lowmem_prunes" status variable to check if the current value
# is high enough for your load.
# Note: In case your tables change very often or if your queries are
# textually different every time, the query cache may result in a
# slowdown instead of a performance improvement.
翻译成中文:
查询缓存用来缓存select结果,当再有相同的查询时,可以直接返回缓存结果,而不用再一次的实际的去执行该查询。如果你有大量的相同的查询,并且很少改变表中的数据,使用缓存可以显著的提升响应速度。通过查看“Qcache_lowmem_prunes”的状态,可以检查当前缓存空间是否够用。
注意:如果你的表中数据改变比较频繁,或者你的查询每次都不相同,此时使用查询缓存可能会导致性能的下降,而不是性能的提升。
查询缓存区的碎片整理:
查询缓存使用一段时间之后,一般都会出现内存碎片,为此需要监控相关状态值,并且定期进行内存碎片的整理,碎片整理的操作语句:FLUSH QUERY CACHE;
清空查询缓存区:
1、RESET QUERY CACHE;
或
2、FLUSH TABLES;
补充
(1)当表中数据发生变更后,与该表有关的查询缓存会自动被清空,所以查询缓存不会返回旧的数据。
(2)查询缓存适用于更改不是太频繁的表且有大量相同查询的情况。
<!--EndFragment-->