mysql: 缓存命中率
查询缓存的基本原理
缓存SELECT操作或预处理查询(注释:5.1.17开始支持)的结果集和SQL语句;
新的SELECT语句或预处理查询语句,先去查询缓存,判断是否存在可用的记录集,
判断标准: 与缓存的SQL语句,是否完全一样,区分大小写;
查询缓存的配置
是否启用mysql查询缓存,可以通过2个参数: query_cache_type和query_cache_size,
其中任何一个参数设置为0都意味着关闭查询缓存功能。
query_cache_type值域为:
0(OFF): 关闭 Query Cache 功能,任何情况下都不会使用 Query Cache;
1(ON): 启用查询缓存,只要符合查询缓存的要求,客户端的查询语句和记录集斗可以缓存起来,共其他客户端使用;
2(DEMAND): 启用查询缓存,只要查询语句中添加了参数: sql_cache,且符合查询缓存的要求,客户端的查询语句和记录集,则可以缓存起来,共其他客户端使用;
query_cache_size值域为:
值最小为40K,对于最大值则可以几乎认为无限制。
实际生产环境的应用经验告诉我们,该值并不是越大, 查询缓存的命中率就越高,也不是对服务器负载下降贡献大,反而可能抵消其带来的好处,甚至增加服务器的负载,
至于该如何设置,推荐设置为: 64M, 建议设置不要超过: 256MB
如果不需要缓存:
SELECT SQL_NO_CACHE * FROM my_table WHERE …
SELECT SQL_NO_CACHE * FROM di_app_apprenrenwang_day WHERE date_time='2020-06-15';
SELECT SQL_NO_CACHE date_time, channel, version, dnu, dau FROM di_app_apprenrenwang_day WHERE date_time='2020-06-15';
如果开始缓存:
SELECT SQL_CACHE * FROM my_table WHERE …
SELECT SQL_CACHE date_time, channel, version, dnu, dau FROM di_app_apprenrenwang_day WHERE date_time='2020-06-15';
查看缓存配置:
SHOW GLOBAL STATUS LIKE 'QCache%';
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 数量
命中率和内存使用率的一些算法
query_cache_min_res_unit的估计值:(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
查询缓存命中率 ≈ (Qcache_hits – Qcache_inserts) / Qcache_hits * 100%
查询缓存内存使用率 ≈ (query_cache_size – Qcache_free_memory) / query_cache_size * 100%
InnoDB存储引擎的缓冲池
show global status like 'innodb%read%'\G
通常InnoDB存储引擎缓冲池的命中不应该小于99%,如:
参数说明:
Innodb_buffer_pool_reads: 表示从物理磁盘读取页的次数
Innodb_buffer_pool_read_ahead: 预读的次数
Innodb_buffer_pool_read_ahead_evicted: 预读的页,但是没有读取就从缓冲池中被替换的页的数量,一般用来判断预读的效率
Innodb_buffer_pool_read_requests: 从缓冲池中读取页的次数
Innodb_data_read: 总共读入的字节数
Innodb_data_reads: 发起读取请求的次数,每次读取可能需要读取多个页
什么情况下会从缓存中获取数据
- 一是所采用的SQL文本MYSQL语句是相同的, 一模一样的
- 大小写不敏感的情况
- 要满足二次查询之间,数据记录包括表结构都没有被更改过
- 默认字符集不同是一种特别容易忽略的情形。
通常情况下,如果客户端与服务器之间所采用的默认字符集不同,则即使查询语句相同、在两次查询之间记录与表结构也没有被更改,系统仍然认为是不同的查询。
如何提高缓存命中率
- 一是在配置时,客户端与服务器端要使用完全相同的字符集。如果客户端(或者说第三方工具)与服务器端使用的字符集不同,那么任何情况下都不会使用缓存功能。
- 在客户端上,要固化查询的语句,尽可能的使用固定相似的查询语句。
- 提高缓存配置, 提高缓存空间, 提升命中率。
- 通过分区表, 越是数据不动的表缓存命中率越高。

浙公网安备 33010602011771号