首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > Mysql >

(转)看下去很美:MySQL Query Cache

2012-12-03 
(转)看上去很美:MySQL Query Cache当你的数据库打开了Query Cache(简称QC)功能后,数据库在执行SELECT语句

(转)看上去很美:MySQL Query Cache

当你的数据库打开了Query Cache(简称QC)功能后,数据库在执行SELECT语句时,会将其结果放到QC中,当下一次处理同样的SELECT请求时,数据库就会从QC取得结果,而不需要去数据表中查询。

(转)看下去很美:MySQL Query Cache

?

在这个“Cache为王”的时代,我们总是通过不同的方式去缓存我们的结果从而提高响应效率,但一个缓存机制是否有效,效果如何,却是一个需要好好思考的问题。在MySQL中的Query Cache就是一个适用较少情况的缓存机制。在上图中,如果缓存命中率非常高的话,有测试表明在极端情况下可以提高效率238%[1]。但实际情况如何?Query Cache有如下规则,如果数据表被更改,那么和这个数据表相关的全部Cache全部都会无效,并删除之。这里数据表更改包括:?INSERT,?UPDATE,DELETE,?TRUNCATE,?ALTER TABLE,?DROP TABLE, or?DROP DATABASE等。举个例子,如果数据表posts访问频繁,那么意味着它的很多数据会被QC缓存起来,但是每一次posts数据表的更新,无论更新是不是影响到了cache的数据,都会将全部和posts表相关的cache清除。如果你的数据表更新频繁的话,那么Query Cache将会成为系统的负担。有实验表明,糟糕时,QC会降低系统13%[1]的处理能力。

如果你的应用对数据库的更新很少,那么QC将会作用显著。比较典型的如博客系统,一般博客更新相对较慢,数据表相对稳定不变,这时候QC的作用会比较明显。

再如,一个更新频繁的BBS系统。下面是一个实际运行的论坛数据库的状态参数:

QCache_hit

5280438

QCache_insert

8008948

Qcache_not_cache

95372

Com select

8104159

可以看到,数据库一共往QC中写入了约800W次缓存,但是实际命中的只有约500W次。也就是说,每一个缓存的使用率约为0.66次。很难说,该缓存的作用是否大于QC系统所带来的开销。但是有一点是很肯定的,QC缓存的作用是很微小的,如果应用层能够实现缓存,将可以忽略QC的效果。

MySQL Query Cache

顾名思义,MySQL Query Cache?就是用来缓存和?Query?相关的数据的。具体来说,Query Cache?缓存了我们客户端提交给?MySQL?的?SELECT?语句以及该语句的结果集。大概来讲,就是将SELECT?语句和语句的结果做了一个?HASH?映射关系然后保存在一定的内存区域中。

在大部分的?MySQL?分发版本中,Query Cache?功能默认都是打开的,我们可以通过调整MySQL Server?的参数选项打开该功能。主要由以下5个参数构成:

·?????????query_cache_limit:允许?Cache?的单条?Query?结果集的最大容量,默认是1MB,超过此参数设置的?Query?结果集将不会被?Cache

·?????????query_cache_min_res_unit:设置?Query Cache?中每次分配内存的最小空间大小,也就是每个Query?的?Cache?最小占用的内存空间大小

·?????????query_cache_size:设置?Query Cache?所使用的内存大小,默认值为0,大小必须是1024的整数倍,如果不是整数倍,MySQL?会自动调整降低最小量以达到1024的倍数

·?????????query_cache_type:控制?Query Cache?功能的开关,可以设置为0(OFF),1(ON)和2(DEMAND)三种,意义分别如下:

·?????????0(OFF):关闭?Query Cache?功能,任何情况下都不会使用?Query Cache

·?????????1(ON):开启?Query Cache?功能,但是当?SELECT?语句中使用的?SQL_NO_CACHE?提示后,将不使用Query Cache

·?????????2(DEMAND):开启?Query Cache?功能,但是只有当?SELECT?语句中使用了?SQL_CACHE提示后,才使用?Query Cache

·?????????query_cache_wlock_invalidate:控制当有写锁定发生在表上的时刻是否先失效该表相关的?Query Cache,如果设置为?1(TRUE),则在写锁定的同时将失效该表相关的所有?Query Cache,如果设置为0(FALSE)则在锁定时刻仍然允许读取该表相关的?Query Cache。

Query Cache?如何处理子查询的?
这是我遇到的最为常见的一个问题。其实Query Cache?是以客户端请求提交的Query?为对象来处理的,只要客户端请求的是一个?Query,无论这个?Query?是一个简单的单表查询还是多表?Join,亦或者是带有子查询的复杂?SQL,都被当作成一个?Query,不会被分拆成多个?Query?来进行?Cache。所以,存在子查询的复杂Query?也只会产生一个Cache对象,子查询不会产生单独的Cache内容。UNION[ALL]?类型的语句也同样如此。

Query Cache?是以?block?的方式存储的数据块吗?
不是,Query Cache?中缓存的内容仅仅只包含该?Query?所需要的结果数据,是结果集。当然,并不仅仅只是结果数据,还包含与该结果相关的其他信息,比如产生该?Cache?的客户端连接的字符集,数据的字符集,客户端连接的?Default Database等。

Query Cache?为什么效率会非常高,即使所有数据都可以?Cache?进内存的情况下,有些时候也不如使用?Query Cache?的效率高?
Query Cache?的查找,是在MySQL?接受到客户端请求后在对?Query?进行权限验证之后,SQL?解析之前。也就是说,当?MySQL?接受到客户端的SQL后,仅仅只需要对其进行相应的权限验证后就会通过?Query Cache?来查找结果,甚至都不需要经过?Optimizer?模块进行执行计划的分析优化,更不许要发生任何存储引擎的交互,减少了大量的磁盘?IO?和?CPU?运算,所以效率非常高。

客户端提交的?SQL?语句大小写对?Query Cache?有影响吗?
有,由于?Query Cache?在内存中是以?HASH?结构来进行映射,HASH?算法基础就是组成?SQL?语句的字符,所以必须要整个?SQL?语句在字符级别完全一致,才能在?Query Cache?中命中,即使多一个空格也不行。

一个?SQL?语句在?Query Cache?中的内容,在什么情况下会失效?
为了保证?Query Cache?中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增,修改,删除等,都会使所有引用到该表的?SQL?的?Query Cache?失效。

为什么我的系统在开启了?Query Cache?之后整体性能反而下降了?
当开启了?Query Cache?之后,尤其是当我们的?query_cache_type?参数设置为?1?以后,MySQL?会对每个SELECT?语句都进行?Query Cache?查找,查找操作虽然比较简单,但仍然也是要消耗一些?CPU?运算资源的。而由于?Query Cache?的失效机制的特性,可能由于表上的数据变化比较频繁,大量的Query Cache?频繁的被失效,所以Query Cache?的命中率就可能比较低下。所以有些场景下,Query Cache?不仅不能提高效率,反而可能造成负面影响。

如何确认一个系统的?Query Cache?的运行是否健康,命中率如何,设置量是否足够?
MySQL?提供了一系列的Global Status?来记录Query Cache?的当前状态,具体如下:

·?????????Qcache_free_blocks:目前还处于空闲状态的?Query Cache?中内存?Block?数目

·?????????Qcache_free_memory:目前还处于空闲状态的?Query Cache?内存总量

·?????????Qcache_hits:Query Cache?命中次数

·?????????Qcache_inserts:向?Query Cache?中插入新的?Query Cache?的次数,也就是没有命中的次数

·?????????Qcache_lowmem_prunes:当?Query Cache?内存容量不够,需要从中删除老的?Query Cache?以给新的?Cache?对象使用的次数

·?????????Qcache_not_cached:没有被?Cache?的?SQL?数,包括无法被?Cache?的?SQL?以及由于query_cache_type?设置的不会被Cache?的?SQL

·?????????Qcache_queries_in_cache:目前在?Query Cache?中的?SQL?数量

·?????????Qcache_total_blocks:Query Cache?中总的?Block?数量

根据简朝阳《mysql性能调优与架构设计》一书中表示Query cache的命中率是:
Qcache_hits / ( Qcache_hits + Qcache_inserts )?×?100%


可以根据这几个状态计算出?Cache?命中率,计算出?Query Cache?大小设置是否足够,总的来说,我个人不建议将?Query Cache?的大小设置超过256MB,这也是业界比较常用的做法。

?

http://blog.sina.com.cn/s/blog_6238358c01013efk.html

热点排行