QueryCache的工作原则是:执行查询最快的方式就是不去执行。QueryCache的组件图和流程图如下所示:
QueryCache的主要可配置系统变量如下所示:
表示mysqld是否支持QueryCache。
表示QueryCache可以缓存的单条查询的最大结果集的大小,默认值为1MB。如果某次查询的结果集大小超过这个系统变量的值,那么QueryCache就不会缓存这次查询的结果集。
表示MySQL为QueryCache每次分配内存的最小空间大小,也就是用于缓存查询结果的最小内存空间的大小,默认值为4KB。
表示QueryCache可以使用的最大内存空间的大小,默认值为1MB。设置的值必须是1024的整数倍,若不是整数倍,MySQL则会自动调整降低至达到1024倍数的最大值。
表示QueryCache的工作模式,同时也是QueryCache功能的开关,可以设置为0(OFF)、1(ON)和2(DEMAND)三种值:
以上环境变量经常需要调整的是query_cache_limit和query_cache_min_res_unit,它们都需要根据实际业务进行相应的调整。例如,如果缓存的查询结果集大多数都小于4KB的话,则可以适当的调整query_cache_min_res_unit的值,以避免造成内存的浪费。如果查询结果集的大小又都大于1MB时,就需要调整query_cache_limit的值,避免因为结果集大小超过限制而不被缓存。
MySQL提供一系列的状态变量来记录QueryCache的当前状态,使你能够确认QueryCache的运行是否健康、命中率如何、内存空间大小是否足够,等等。QueryCache的状态变量如下所示:
表示QueryCache中目前还有多少空闲的内存块。如果该值比较大,则说明QueryCache中的内存碎片可能比较多。FLUSHQUERYCACHE会对缓存中的碎片进行整理,从而得到一个较大的空闲内存块。
表示QueryCache目前空闲的内存大小。
表示有多少次查询在QueryCache命中。
向QueryCache中插入新记录的次数,也就是查询没有命中的次数。
表示由于QueryCache的内存不足而从缓存中删除的查询结果的数量。如果这个数值在不断增长,那么一般是QueryCache的空闲内存不足(通过Qcache_free_memory判断),或者内存碎片较严重(通过Qcache_free_blocks判断)。
表示没有被缓存的查询数量。有三种情况会导致查询结果不会被缓存:其一,由于query_cache_type的设置;其二,查询不是SELECT语句;其三,使用了now()之类的函数,导致查询语句一直在变化。
表示QueryCache中当前包含的查询结果数量。
表示QueryCache中的内存块总数量。
QueryCache的查询,发生在MySQL接收到客户端的查询请求、查询权限验证之后和查询SQL解析之前。也就是说,当MySQL接收到客户端的查询SQL之后,仅仅只需要对其进行相应的权限验证之后,就会通过QueryCache来查找结果,甚至都不需要经过Optimizer模块进行执行计划的分析优化,更不需要发生任何存储引擎的交互。由于QueryCache是基于内存的,直接从内存中返回相应的查询结果,因此减少了大量的磁盘I/O和CPU计算,导致效率非常高。
即使QueryCache的优点很明显,但是也不能忽略它所带来的一些缺点:
实际上,并不是所有表都适合使用QueryCache。造成QueryCache失效的原因主要是相应的表发生了变更,那么就应该避免在变更频繁的表上使用QueryCache。MySQL针对QueryCache有两个专用的SQL选项:SQL_NO_CACHE和SQL_CACHE。若将query_cache_type设置为1(ON),那么通过SQL_NO_CACHE选项便能强制不使用QueryCache;若将query_cache_type设置为2(DEMAND),那么通过SQL_CACHE选项便能强制使用QueryCache。通过强制不使用QueryCache,可以让MySQL在频繁变更的表上不使用QueryCache,这样减少了内存开销,也减少了hash计算和查找的开销。
无论MySQL收到的查询语句是单表还是多表或是包含子查询的SQL,都被作为一个查询,不会被分拆成多个查询来进行缓存,包括Union语句。
有影响。由于QueryCache在内存中是以hash结构来进行映射的,hash算法的基础就是组成查询语句的字符,所以必须要整个查询语句在字符级别完全一致,才能在QueryCache中命中。
为了保证QueryCache中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增、修改、删除等,都会使所有引用到该表的QueryCache缓存数据失效。
QueryCache碎片率=Qcache_free_blocks/Qcache_total_blocks*100%如果QueryCache碎片率超过20%,则可以用FLUSHQUERYCACHE整理内存碎片;如果你的查询都是小数据量的话,可以尝试减小query_cache_min_res_unit。
QueryCache利用率=(query_cache_size-Qcache_free_memory)/query_cache_size*100%
QueryCache利用率在25%以下的话,说明query_cache_size设置的过大,可适当减小;QueryCache利用率在80%以上,而且Qcache_lowmem_prunes>50的话,说明query_cache_size可能有点小,或者就是内存碎片太多。
①可缓存查询的QueryCache命中率=Qcache_hits/(Qcache_hits+Qcache_inserts)*100%②涵盖所有查询的QueryCache命中率=Qcache_hits/(Qcache_hits+Com_select)*100%
若命中率在50-70%的范围之内,则表明QueryCache的缓存效率较高。如果命中率明显小于50%,那么建议禁用(将query_cache_type设置为0(OFF))或按需使用(将query_cache_type设置为2(DEMAND))QueryCache,节省的内存可以用作InnoDB的缓冲池。
如果Qcache_lowmem_prunes值比较大,表示QueryCache的内存空间大小设置太小,需要增大。
如果Qcache_free_blocks值比较大,表示内存碎片较多,需要使用FLUSHQUERYCACHE语句清理内存碎片。
query_cache_min_res_unit的计算公式如下所示:
query_cache_min_res_unit=(query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache
其中,一般不建议将QueryCache的大小(也就是query_cache_size系统变量)设置超过256MB。
MySQL的查询缓存并非缓存执行计划,而是查询及其结果集,这就意味着只有相同的查询操作才能命中缓存,因此MySQL的查询缓存命中率很低,另一方面,对于大结果集的查询,其查询结果可以从cache中直接读取,有效的提升了查询效率。
那么如何设置缓存的大小呢?来看一下:
1、在mysql客户端命令行中我们可以这么查看缓存是否开启以及缓存设置的大小:
mysql>showvariableslike'%query_cache%';+------------------------------+-------------+|Variable_name|Value|+------------------------------+-------------+|have_query_cache|YES||query_cache_limit|1048576||query_cache_min_res_unit|4096||query_cache_size|16106127360||query_cache_type|ON||query_cache_wlock_invalidate|OFF|+------------------------------+-------------+6rowsinset(0.01sec)其中:
query_cache_type:是否开启缓存功能,取值为ON,OFF,DEMAND,默认值为ON-值为OFF或0时,查询缓存功能关闭;-值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存;-值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存
query_cache_wlock_invalidate:表示当有其他客户端正在对MyISAM表进行写操作时,如果查询在querycache中,是否返回cache结果还是等写操作完成再读表获取结果。
query_cache_limit指定单个查询能够使用的缓冲区大小,缺省为1M;
query_cache_min_res_unit为系统分配的最小缓存块大小,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费;query_cache_size:表示缓存的大小。
了解了以上的指标后我们就可以在mysql的配置文件my.cnf中进行设置。然后重启mysl服务器即可。在[mysqld]下面添加参数。一般是设置query_cache_size和query_cache_type两项。
2、上面查看的是我们进行缓存的配置,它一般从配置文件中读取值,但是有时候我们需要实时查看当前mysql中的数据缓存大小。
mysql>showstatuslike'%qcache%';+-------------------------+----------+|Variable_name|Value|+-------------------------+----------+|Qcache_free_blocks|1||Qcache_free_memory|1031832||Qcache_hits|0||Qcache_inserts|0||Qcache_lowmem_prunes|0||Qcache_not_cached|16489053||Qcache_queries_in_cache|0||Qcache_total_blocks|1|+-------------------------+----------+8rowsinset(0.00sec)解释:
Qcache_free_memory:缓存中的空闲内存。
Qcache_total_blocks:缓存中块的数量。
3、清空缓存:
flushquerycache命令
加大缓存有助于我们查询的效率提高:
这里举个例子:
mysql>usemob_adnDatabasechangedmysql>selectcount(*)fromcreative_output;+----------+|count(*)|+----------+|87151154|+----------+1rowinset(3min18.29sec)mysql>selectcount(*)fromcreative_output;+----------+|count(*)|+----------+|87151154|+----------+1rowinset(0.00sec)mysql>selectcount(*)fromcreative_output;+----------+|count(*)|+----------+|87151154|+----------+1rowinset(0.00sec)可以看到缓存真的很厉害。
还有的同学会想到innodb_buffer_pool这个参数,两者的作用与区别我会接着来讲。