MYSQL笔记(MySQL查询缓存)

查询缓存保存了完整的SELECT结果集;这样当一个相同的查询到达时,可服务器可以跳过解析、优化、执行等阶段,直接把结果返回给客户端,但某种意义上讲,查询缓存实际上修改了应用程序请求的语义,例如,即使在LOCK TABLES的情况下,查询也能被缓存下来。

在服务器端维护了一个查找表,查找的键是查询文本、数据库和客户端协议版本及其他影响实际查询结果的因素,综合起来的哈希值,也就是说,只要客户端的查询语句有丝毫的差异,都不会命中缓存,或者查询语句相同,但不同的客户端协议版本也可能无法命中查询缓存;

此外一些有不确定结果的查询,如NOW()、CURRENT_DATE()这样的函数,查询结果不会被缓存;不会缓存的情况包括

1.用户自定义函数

2.存储函数

3.用户自定义变量

4.临时表

5.任何一个有列级权限的表的查询

在执行的过程中,MYSQL一旦发现有阻止缓存的元素存在,就将其标记为不可缓存。

在InnoDB中,当事务内部改写了表,虽然多版本机制应当对其他语句隐藏变化,但这里却会使所有引用了该表的查询缓存失效,直到事务提交之前,该表都是全局不可缓存的。

当一个请求查询缓存的时,将会阻塞所有访问缓存的查询。

---------------------------

缓存内容存储在内存中,查询缓存具有一个内存池,这在服务器启动时进行初始化,分配给查询缓存的大小是可配置的,除了查询缓存本身固定需要的40KB空间,其他都用于内存池。

由于服务器是逐行发送结果的,在执行完毕前,无法知道缓存需要的内存大小,因此,当需要缓存结果时,会先从池中获取一个至少query_cache_min_res_unit大小的块,将数据写入其中,当还有剩余数据时,就需要另外申请新块,继续加入数据,最后,当保存完毕后,如果数据块还没存满,就会将空的部分截出来,加入到剩余的空闲空间中。

在上述过程中,可能会产生很多碎片,这些碎片因为低于最小限制,无法重复使用,可以通过命令FLUSH QUERY CACHE来移除碎片。

在文件sql/sql_cache.cc中对上述过程进行了具体的描述。

----------------------------

在status变量列表里,Qcache_hits记录了命中次数,另外还有Qcache_inserts记录存储缓存的次数,Qcache_free_blocks记录了空闲块数

关于查询缓存,用到的几个全局变量包括:

1.Query_cache_type,表示缓存是否被激活,OFF、ON、DEMAND(该选项意味着只有包含了SQL_Cache选项的查询才会被缓存);

2.Query_cache_size,分配给查询缓存的大小;

3.Query_cache_min_res_unit,分配缓存块的最小值;

4.Query_cache_limit,存储结果最大值,若超过了会丢弃已缓存的值,因此当预知到可能结果超出时,最好加上选项SQL_NO_CACHE,避免额外开销;

5.Query_cache_wlock_invalidate,默认为OFF,可以读取已锁定的表的缓存数据

-----------------------------

通用的查询缓存优化方案:

1.尽量使用多个小表而非大表;

2.成批进行写入操作而非逐个执行;

3.设置合适的query_cache_size值;

4.使用SQL_CACHE和SQL_NO_CACHE来决定是否缓存查询;

5.对很多写入任务的应用程序,关闭查询缓存。

你可能感兴趣的:(mysql)