Query Cache

1. 存储Query,并且存储result
2. cache会跟踪哪些table被使用了,是否被修改了,
3. 对应用程序透明
4. 使用hash去查找;任何大小写、空格、注释都会影响命中
   结果需要是确定性的:now() current_user() current_date() result都不会被缓存
5. 会增加系统负载,一般不大:check cache;缓存结果;数据被更新,需要使cache过期   
   对于InnoDB来讲,如果一个事务修改了一张表,那么cache中table相关query是要置为无效的,而且在事务期间都不能被cache
   如果cache中query过多,置为无效也需要一定时间(可能很长)
   
Cache如何使用内存
1. 40K固定大小的常用内存,使用可变长的block,每个block知道他的类型(result,query使用哪些表,query文本)、大小、记录数
2. 使用时首先分配query_cache_min_res_unit,不会分精确,因为result set在它分配后才会定下来(不是一起传给内存,而是生成一条row传一条)
3. 如果有并发查询,分配的大小不合适,慢慢会增加内存碎片,碎片太小不能用于其他缓存
 
cache是否有效
1. Hit rate:cache中的query/server执行的query;Qcache_hits/(Qcache_hits+Com_select)
2. cache miss的原因
query不能cache:含有不确定结果now();结果集太多 两种情况都会增加Qcache_not_cached 
没执行过
数据过期 被server删掉
3. 如果cache miss多,而uncachable query不多:
server刚启动,还没开始缓存
没执行过的query很多
cache失效很多(碎片,内存不够,数据修改)
数据修改记录(Com_* status Com_update, Com_delete等)
由于低内存而导致的无效query数量:Qcache_lowmem_prunes
4. query cache会增加update的负载:每个update都会去cache查看是否有query需要置为invalid
5. 如果com_select与Qcache_insert相同说明失效过多,Qcache_insert应该比com_select小很多
com_select等于qcache_inserts(失效) + qcache_not_cache + 权限检查错误的
qcache_inserts这个计数不是表示没被缓存而进行的读,而是缓存失效而进行的读,没被缓存和缓存失效是两个概念,分别计数,但都会引起com_select
6. 调试维护Query Cache
query_cache_type:是否开启cache(OFF, ON,or DEMAND),第三个只有在sql中定义了SQL_CACHE才会缓存
query_cache_size:cache分配的全部内存大小,单位K
query_cache_min_res_unit:block最小单位
query_cache_limit:可以被cache的最大结果集
query_cache_wlock_invalidate:默认off,一个connection可以读另外一个connection锁定表的数据
减少碎片
无法完全避免,但是精心选择query_cache_min_res_unit可以避免浪费内存
需要在分配大小与数量之间找平衡(过小,会分配过多,增加cpu负担;过大 碎片多)
cache中query平均大小:(query_cache_size – Qcache_free_memory)/Qcache_queries_in_cache
通常缓存大result都没啥好处,通过query_cache_limit限制
Qcache_free_blocks:Free的block;达到Qcache_total_blocks/2冲突会激烈;Qcache_lowmem_prunes在增加但是有很多FreeBlock就是碎片引起的query被cache删除
FLUSH QUERY CACHE会减少碎片,但是cache此时不可访问
RESET QUERY CACHE会清空cache
改善cache使用
如果无碎片但是hit还是不高,可能是内存分配不够,她回挤掉其他缓存的query:Qcache_lowmem_prunes增加
未使用的内测:Qcache_free_memory
如果很多freeBlock 碎片也不多 被挤掉也不多:频繁更新,不可缓存
不确定cache是否有益:query_cache_size设为0,测benchMark
7. InnoDB和Query Cache
InnoDB使用MVCC,在4.0之前完全禁用cache,4.1开始由InnoDB通知server(基于每张表)事务是否可以访问cache(从cache读,吧result写入cache)
访问控制通过:事务ID 表是否有锁;每个表在内存中的数据字典都有一个对应的事务id号,比这个id号小的事务是不能读写cache中与表相关的query的
。。。。。。 没看懂,需要在研究
8. 常用的优化方案
多张小表而不是一张大表有助于缓存
批量写比一条一条写有效,因为只invalide cache一次
在invalide和排挤其他query时 server会延迟很长一段时间,所以不要把query_cache_size设的太大,256M足矣
不能在db或表级别限制cache,但是可以在sql中声明SQL_CACHE and SQL_NO_CACHE;session level的query_cache_type可以限制到connection级别是否做cache
在写逻辑频繁的系统,禁用cache性能会得到提升
9. Query cache的可选方案
client cache