mysql之Query Cache

1,QueryCache的实现原理;

  1、目前只有select语句会被cache,其他类似show,use的语句则不会被cache。

  2、两个SQL语句,只要相差哪怕是一个字符(例如大小写不一样;多一个空格等),那么这两个SQL将使用不同的一个CACHE。

一个被频繁更新的表如果被应用了QC,可能会加重数据库的负担,而不是减轻负担。我一般的做法是默认打开QC,而对一些涉及频繁更新的表的SQL语句加上SQL_NO_CACHE关键词来对其禁用CACHE。这样可以尽可能避免不必要的内存操作,尽可能保持内存的连续性。那些查询很分散的SQL语句,也不应该使用QC。例如用来查询用户和密码的语句——“select pass from user where name='surfchen'”。这样的语句,在一个系统里,很有可能只在一个用户登陆的时候被使用。每个用户的登陆所用到的查询,都是不一样的SQL文本,QC在这里就几乎不起作用了,因为缓存的数据几乎是不会被用到的,它们只会在内存里占地方。


2,QueryCache的负面影响:
    1,Query的hash性能问题和命中率问题;
    2,查询缓存及其容易失效;当表内容发生变化或者表结构发生变化,对应的查询缓存内容都会失效;
    3,查询缓存中的结果容易产生重复;因为查询缓存中缓存的是查询结果,所以不同的查询的结果很容易重复;

3,Query Cache的使用:
    1,设置query_cache_limit为查询缓存大小,如果为0,则不使用查询缓存;
    2,使用SQL_CACHE或者SQL_NO_CACHE来强制是否使用查询缓存;
    3,查询查询缓存设置:show variables like '%query_cache%';
        1,“have_query_cache”:该MySQL 是否支持Query Cache;
        2,“query_cache_limit”:Query Cache 存放的单条Query 最大Result Set ,默认1M;
        3,“query_cache_min_res_unit”:Query Cache 每个Result Set 存放的最小内存大小,默认4k;
        4,“query_cache_size”:系统中用于Query Cache 内存的大小;
        5,“query_cache_type”:系统是否打开了Query Cache 功能;


    4,查询查询缓存使用情况:show status like 'Qcache%';
        1,“Qcache_free_blocks”:Query Cache 中目前还有多少剩余的blocks。如果该值显示较大,则说明Query Cache 中的内存碎片较多了
        2,“Qcache_free_memory”:Query Cache 中目前剩余的内存大小;
        3,“Qcache_hits”:多少次命中;
        4,“Qcache_inserts”:多少次未命中然后插入;Query Cache 命中率= Qcache_hits / ( Qcache_hits + Qcache_inserts );
        5,“Qcache_lowmem_prunes”:多少条Query 因为内存不足而被清除出Query Cache;
        6,“Qcache_not_cached”:因为query_cache_type 的设置或者不能被cache 的Query 的数量;
        7,“Qcache_queries_in_cache”:当前Query Cache 中cache 的Query 数量;
        8,“Qcache_total_blocks”:当前Query Cache 中的block 数量;

    5,query cache的使用限制:
        1,mysql query cache内容为 select 的结果集, cache 使用完整的 sql 字符串做 key, 并区分大小写,空格等。即两个sql必须完全一致才会导致cache命中。
        2,prepared statement永远不会cache到结果,即使参数完全一样,
        3,where条件中如包含了某些函数永远不会被cache, 比如current_date, now等。
        4,太大的result set不会被cache (< query_cache_limit)

    6,query cache的使用方式:
        1,如果没有绝对的使用把握,可以关闭查询缓存;
        2,如果要使用查询缓存,最好能够精确的控制那些表内容放到查询缓存,哪些表不用查询缓存;

存储块block说明

在本节里“存储块”和“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的大小。

Qcache_queries_in_cache*query_cache_min_res_unit(sql文本和表信息所在的block占用的内存很小,可以忽略)如果远远大于query_cache_size-Qcache_free_memory,那么可以尝试减小query_cache_min_res_unit的值。


参考自:http://blog.csdn.net/iris_xuting/article/details/50495928#t0


posted @ 2019-09-24 08:47  AppleLife  阅读(273)  评论(0编辑  收藏  举报