mysql select缓存机制使用详解
mysqlQueryCache默认为打开。从某种程度可以提高查询的效果,但是未必是最优的解决方案,如果有的大量的修改和查询时,由于修改造成的cache失效,会给服务器造成很大的开销,可以通过query_cache_type【0(OFF)1(ON)2(DEMAND)】来控制缓存的开关.
需要注意的是mysqlquerycache是对大小写敏感的,因为QueryCache在内存中是以HASH结构来进行映射,HASH算法基础就是组成SQL语句的字符,所以任何sql语句的改变重新cache,这也是项目开发中要建立sql语句书写规范的原因吧
1.何时cache
a)mysqlquerycache内容为select的结果集,cache使用完整的sql字符串做key,并区分大小写,空格等。即两个sql必须完全一致才会导致cache命中。
b)preparedstatement永远不会cache到结果,即使参数完全一样。据说在5.1之后会得到改善。
c)where条件中如包含了某些函数永远不会被cache,比如current_date,now等。
d)date之类的函数如果返回是以小时或天级别的,最好先算出来再传进去。
select*fromfoowheredate1=current_date--不会被cache
select*fromfoowheredate1='2008-12-30'--被cache,正确的做法
e)太大的resultset不会被cache(
2.何时invalidate
a)一旦表数据进行任何一行的修改,基于该表相关cache立即全部失效。
b)为什么不做聪明一点判断修改的是否cache的内容?因为分析cache内容太复杂,服务器需要追求最大的性能。
3.性能
a)cache未必所有场合总是会改善性能
当有大量的查询和大量的修改时,cache机制可能会造成性能下降。因为每次修改会导致系统去做cache失效操作,造成不小开销。
另外系统cache的访问由一个单一的全局锁来控制,这时候大量>的查询将被阻塞,直至锁释放。所以不要简单认为设置cache必定会带来性能提升。
b)大resultset不会被cache的开销
太大的resultset不会被cache,但mysql预先不知道resultset的长度,所以只能等到resetset在cache添加到临界值query_cache_limit之后才会简单的把这个cache丢弃。这并不是一个高效的操作。如果mysqlstatus中Qcache_not_cached太大的话,则可对潜在的大结果集的sql显式添加SQL_NO_CACHE的控制。
query_cache_min_res_unit=(query_cache_size–Qcache_free_memory)/Qcache_queries_in_cache
4.内存池使用
mysqlquerycache使用内存池技术,自己管理内存释放和分配,而不是通过操作系统。内存池使用的基本单位是变长的block,一个resultset的cache通过链表把这些block串起来。因为存放resultset的时候并不知道这个resultset最终有多大。block最短长度为query_cache_min_res_unit,resultset的最后一个block会执行trim操作。
QueryCache在提高数据库性能方面具有非常重要的作用。
其设定也非常简单,仅需要在配置文件写入两行:query_cache_type和query_cache_size,而且MySQL的querycache非常快!而且一旦命中,就直接发送给客户端,节约大量的CPU时间。
当然,非SELECT语句对缓冲是有影响的,它们可能使缓冲中的数据过期。一个UPDATE语句引起的部分表修改,将导致对该表所有的缓冲数据失效,这是MySQL为了平衡性能而没有采取的措施。因为,如果每次UPDATE需要检查修改的数据,然后撤出部分缓冲将导致代码的复杂度增加。
query_cache_type0代表不使用缓冲,1代表使用缓冲,2代表根据需要使用。
设置1代表缓冲永远有效,如果不需要缓冲,就需要使用如下语句:
代码如下
SELECTSQL_NO_CACHE*FROMmy_tableWHERE...
如果设置为2,需要开启缓冲,可以用如下语句:
代码如下
SELECTSQL_CACHE*FROMmy_tableWHERE...
用SHOWSTATUS可以查看缓冲的情况:
代码如下
mysql>showstatuslike'Qca%'; +-------------------------+----------+ |Variable_name|Value| +-------------------------+----------+ |Qcache_queries_in_cache|8| |Qcache_inserts|545875| |Qcache_hits|83951| |Qcache_lowmem_prunes|0| |Qcache_not_cached|2343256| |Qcache_free_memory|33508248| |Qcache_free_blocks|1| |Qcache_total_blocks|18| +-------------------------+----------+ 8rowsinset(0.00sec)
如果需要计算命中率,需要知道服务器执行了多少SELECT语句:
代码如下
mysql>showstatuslike'Com_sel%'; +---------------+---------+ |Variable_name|Value| +---------------+---------+ |Com_select|2889628| +---------------+---------+ 1rowinset(0.01sec)
在本例中,MySQL命中了2,889,628条查询中的83,951条,而且INSERT语句只有545,875条。因此,它们两者的和和280万的总查询相比有很大差距,因此,我们知道本例使用的缓冲类型是2。
而在类型是1的例子中,Qcache_hits的数值会远远大于Com_select
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。