博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

MySQL查询缓存

Posted on 2020-05-18 14:48  面具下的戏命师  阅读(412)  评论(1编辑  收藏  举报

MySQL查询缓存

MySQL Query Cache 就是用来缓存和 Query 相关的数据的。具体来说,Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集。大概来讲,就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中。它不需要经过Optimizer模块进行执行计划的分析优化,更不需要发生同任何存储引擎的交互,减少了大量的磁盘IO和CPU运 算,所以有时候效率非常高。

缓存参数配置

1、 have_query_cache 查看当前的MySQL数据库是否支持查询缓存,YES代表支持。

2、 query_cache_type 查看当前MySQL是否开启了查询缓存 ,默认是关闭的。它的取值有3个:

含义
OFF或0 查询缓存功能关闭
ON或1 查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存
DEMAND或2 查询缓存功能按需进行,显式指定 SQL_CACHE 的SELECT语句才会缓存;其它均不予缓存


 3、query_cache_size 缓存使用的总内存空间大小,单位是字节,这个值必须是1024的整数倍。

 4、query_cache_limit 允许缓存的单条查询结果集的最大容量,默认是1MB,超过此参数设置的查询结果集将不会被缓存;

 5、query_cache_min_res_unit 分配内存块时的最小单位大小,设置查询缓存Query Cache每次分配内存的最小空间大小,即每个查询的缓存最小占用的内存空间大小

 6、query_cache_wlock_invalidate  如果某个数据表被锁住,是否仍然从缓存中返回数据,默认是OFF,表示仍然可以返回控制当有写锁定发生在表上的时刻是否先失效该表相关的Query Cache,如果设置为 1(TRUE),则在写锁定的同时将失效该表相关的所有Query Cache,如果设置为0(FALSE)则在锁定时刻仍然允许读取该表相关Query Cach。

缓存查询状态

可以通过 show status like 'Qcache%' 语句来查看查询缓存的使用情况,各变量含义如下:

变量 含义
Qcache_free_blocks 缓存池中空闲块的个数,数目大说明可能有碎片。flush query cache会对缓存中的碎片进行整理,从而得到一个空闲块。
Qcache_free_memory 缓存中空闲内存量
Qcache_hits 缓存命中次数
Qcache_inserts 缓存写入次数
Qcache_lowmem_prunes 因内存不足删除缓存次数
Qcache_not_cached 非缓存查询的数量(由于 query_cache_type 设置而无法缓存或未缓存)
Qcache_queries_in_cache 当前缓存中缓存的SQL数量
Qcache_total_blocks 查询缓存中的块总数

 查询缓存提示

可以在SELECT语句中指定两个与查询缓存相关的选项 :
SQL_CACHE : 如果查询结果是可缓存的,并且 query_cache_type 系统变量的值为ON或 DEMAND ,则缓存查询结果 。
SQL_NO_CACHE : 服务器不使用查询缓存。它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果。

SELECT SQL_CACHE id, name FROM customer;
SELECT SQL_NO_CACHE id, name FROM customer;

查询缓存失效的情况

1、 SQL 语句不一致的情况, 要想命中查询缓存,查询的SQL语句必须完全一致。SQL任何字符上的不同,如大小写、空格、注释、都会导致缓存不命中。

2、当查询语句中有一些不确定的时,则不会缓存。如 : now() , current_date() , curdate() , curtime() , rand() ,uuid() , user() , database()。

3、不使用任何表查询语句。如 select 'A';

4、 查询 mysql, sys,information_schema或 performance_schema 数据库中的表时,不会走查询缓存

5、在存储的函数,触发器或事件的主体内执行的查询。

6、如果表更改,则使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除。这包括使用 MERGE 映射到已更改表的表的查询。一个表可以被许多类型的语句,如被改变 INSERT, UPDATE, DELETE, TRUNCATE TABLE, ALTER TABLE, DROP TABLE,或 DROP DATABASE 。

7、清理查询缓存 & 减少碎片策略  

     FLUSH QUERY_CACHE; 清理查询缓存内存碎片

     RESET QUERY_CACHE; 从查询缓存中移出所有查询

     FLUSH TABLES;  关闭所有打开的表,同时该操作将会清空查询缓存中的内容

缓存的使用时机

衡量打开缓存是否对系统有性能提升是一个很难的话题

1、 通过缓存命中率判断, 缓存命中率 = 缓存命中次数 (Qcache_hits) / 查询次数 (Com_select)

2、通过缓存写入率, 写入率 = 缓存写入次数 (Qcache_inserts) / 查询次数 (Qcache_inserts)

3、通过 命中-写入率 判断, 比率 = 命中次数 (Qcache_hits) / 写入次数 (Qcache_inserts), 高性能MySQL中称之为比较能反映性能提升的指数,一般来说达到3:1则算是查询缓存有效,而最好能够达到10:1

任何事情过犹不及,尤其对于某些写频繁的系统,开启Query Cache功能可能并不能让系统性能有提升,有时反而会有下降。原因是MySql为了保证Query Cache缓存的内容和实际数据绝对一致,当某个数据表发生了更新、删除及插入操作,MySql都会强制使所有引用到该表的查询SQL的Query Cache失效。对于密集写操作,启用查询缓存后很可能造成频繁的缓存失效,间接引发内存激增及CPU飙升,对已经非常忙碌的数据库系统这是一种极大的负担。

查询缓存示例

创建如下表,并利用存储过程插入500万条测试数据:

create table t_sql_cache(id int primary key, name varchar(10), address varchar(20));

drop procedure if exists pro_t_sql_cache_insert;
CREATE PROCEDURE pro_t_sql_cache_insert ( number INT ) 
 BEGIN
    DECLARE i INT DEFAULT 0;
    set autocommit = 0;
    WHILE i < number DO
            SET i = i + 1;
        INSERT INTO t_sql_cache VALUES( i, 'adadcsadc', 'asdeffgtdbdrbtd' );
        if mod(i,5000) = 0 then
          commit;
        end if;
    END WHILE;
  set autocommit = 1;    
 END

call pro_t_sql_cache_insert(5000000);

(1)、关闭查询缓存

(2)、开启查询缓存

 

 (3)、修改其中一个字母大小写,发现不走缓存

 (4)、使用查询缓存提示,不走缓存

 (5)、查看缓存状态