数据库为了提升查询性能,一般都会对查询的一些过程处理结果做一定的缓存,比如查询计划缓存。

当数据库拿到一条sql语句之后,首先就要解析sql,分析语法,生成解析树,然后进入查询优化器生成最终的查询计划;像postgresql, sql server, oracle都会将这条语句的查询计划加入缓存池,如果下一次收到同样的sql语句,则直接跳过,解析,查询优化等步骤,转而直接执行缓存池中对应的查询计划,从而提升性能。

mysql在某些场景下也能实现查询计划的缓存,但是mysql自带的查询缓存则是直接缓存查询的结果集,这样可能就要求查询的缓存内存要设置的不能过小,否则无法发挥应有的性能。

缓存命中:
查询缓存的命中是根据sql语句,数据库版本号等其他元素计算而成的散列值来判断的。很遗憾的是sql语句里面任何的一个不同,包括大小写,空格,注释都会导致缓存命中失败。

可能有些人觉得,mysql应该预处理一下sql语句: 比如转成大写,去掉注释,去掉不必要的空格之后再计算散列值,这样可能会提高缓存的命中率。但是其实这是推卸责任,一条sql如果在一个应用里面被使用了多次,我们就应该保证它不管在哪个地方都是一模一样,每个bit都应该一样,这样缓存自然不会因为空格,大小写等不同而命中失败;所以使用统一的编码规范,或者采用程序自动生成所需的sql语句可以是我们的系统运行的更快。

查询缓存的性能

因为mysql查询缓存是缓存的结果,所以一旦命中,则是直接从内存中返回结果,省去了解析,优化,遍历表等步骤,性能自然会有提升。但是因为缓存会因为数据库的版本号而被清掉,也就是说,只要这个发生了insert、update、delete操作,mysql会把缓存全部清空,也就是说等到下一次查询的时候重新缓存,所以查询缓存在更新很频繁的表并不适用,有时候可能会带来性能的下降。

再者,既然是缓存数据结果,我们可以采用第三方的内存缓存程序在应用端缓存结果,这样还会节省了连接mysql数据库再得到结果的延迟。

查看缓存相关信息  

如果要使用缓存,在配置文件文件中设置query_cache_type的值,可以为OFF、ON、DEMAND,重启mysql就会生效,在客户端设置

 
mysql> set query_cache_type=ON;

只对当前客户端有效。

查看缓存相关的配置信息,可以使用下面的语句查看:

mysql> show variables like '%query_cache%';

+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| have_query_cache             | YES      |
| query_cache_limit            | 8388608  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 |
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

1. query_cache_type: 是否打开缓存

可选项

1) OFF: 关闭

2) ON: 总是打开

3) DEMAND: 只有明确写了SQL_CACHE的查询才会吸入缓存

2. query_cache_size: 缓存使用的总内存空间大小,单位是字节,这个值必须是1024的整数倍,否则MySQL实际分配可能跟这个数值略有不同。

3. query_cache_min_res_unit: 分配内存块时的最小单位大小,选择合适的大小,可以有效的减少碎片化,这需要根据实际的查询结果的平均大小调整。

4. query_cache_limit: MySQL能够缓存的最大结。

5. query_cache_wlock_invalidate: 如果某个数据表被锁住,是否仍然从缓存中返回数据,默认是OFF,表示仍然可以返回。

查询缓存状态可以使用下面的语句查询:

mysql> show status like "%Qcache%";
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 16768392 |
| Qcache_hits             | 0        |
| Qcache_inserts          | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 103      |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+

参数含义如下:

Qcache_free_blocks: 缓存池中空闲块的个数

Qcache_free_memory: 缓存中空闲内存量

Qcache_hits: 缓存命中次数

Qcache_inserts: 缓存写入次数

Qcache_lowmen_prunes: 因内存不足删除缓存次数

Qcache_not_cached: 查询未被缓存次数,例如查询结果超出缓存块大小,查询中包含可变函数等

Qcache_queries_in_cache: 当前缓存中缓存的SQL数量

Qcache_total_blocks: 缓存总block数