MySQL的查询缓存

Mysql查询缓存机制原理QueryCache,QueryCache是根据SQL语句来cache的。一个SQL查询如果以select开头,那么 MySQL服务器将尝试对其使用 QC。每个Cache都是以SQL文本作为key来存的。在应用QueryCache之前,SQL文本不会被作任何处理。也就是说,两个SQL语句,只要 相差哪怕是一个字符(例如大小写不一样;多一个空格等),那么这两个SQL将使用不同的一个QueryCache。

不过SQL文本有可能会被客户端做一些处理。例如在官方的命令行客户端里,在发送SQL给服务器之前,会做如下处理:
过滤所有注释
去掉SQL文本前后的空格,TAB等字符。注意,是文本前面和后面的。中间的不会被去掉。

下 面的三条SQL里,因为SELECT大小写的关系,最后一条和其他两条在QC里肯定是用的不一样的存储位置。而第一条和第二条,区别在于后者有个注释,在 不同客户端,会有不一样的结果。所以,保险起见,请尽量不要使用动态的注释。在PHP的mysql扩展里,SQL的注释是不会被去掉的。也就是三条 SQL会被存储在三个不同的缓存里,虽然它们的结果都是一样的。
select * FROM people where name='surfchen';
select * FROM people where /*hey~*/name='surfchen';
SELECT * FROM people where name='surfchen';

目前只有select语句会被cache,其他类似show,use的语句则不会被cache。

因为QC是如此前端,如此简单的一个缓存系统,所以如果一个表被更新,那么和这个表相关的SQL的所有QC都会被失效。假设一个联合查询里涉及到了表A和表B,如果表A或者表B的其中一个被更新(update或者delete),这个查询的QC将会失效。

也 就是说,如果一个表被频繁更新,那么就要考虑清楚究竟是否应该对相关的一些SQL进行QC了。一个被频繁更新的表如果被应用了QueryCache,可能 会加重Mysql数据库的负担,而不是减轻Mysql负担。我一般的做法是默认打开QueryCache,而对一些涉及频繁更新的表的SQL语句加上 SQL_NO_CACHE关键词来对其禁用CACHE。这样可以尽可能避免不必要的内存操作,尽可能保持内存的连续性。

那些查询很分散的 SQL语句,也不应该使用缓存。例如用Mysql来查询用户和密码的语句——“select pass from user where name='surfchen'”。这样的语句,在一个系统里,很有可能只在一个用户登陆的时候被使用。每个用户的登陆所用到的查询,都是不一样的SQL 文本,QueryCache在这里就几乎不起作用了,因为缓存的数据几乎是不会被用到的,它们只会在内存里占地方。
存储块
在本节里“存储块”和“block”是同一个意思

QueryCache 缓存一个查询结果的时候,一般情况下不是一次性地分配足够多的内存来缓存结果的。而是在查询结果获得的过程中,逐块存储。当一个存储块被填满之后,一个新 的存储块将会被创建,并分配内存(allocate)。单个存储块的内存分配大小通过query_cache_min_res_unit参数控制,默认为 4KB。最后一个存储块,如果不能被全部利用,那么没使用的内存将会被释放。如果被缓存的结果很大,那么会可能会导致分配内存操作太频繁,系统系能也随之 下降;而如果被缓存的结果都很小,那么可能会导致内存碎片过多,这些碎片如果太小,就很有可能不能再被分配使用。

除了查询结果需要存储块 之外,每个SQL文本也需要一个存储块,而涉及到的表也需要一个存储块(表的存储块是所有线程共享的,每个表只需要一个存储块)。存储块总数量=查询结果 数量*2+涉及的数据库表数量。也就是说,第一个缓存生成的时候,至少需要三个存储块:表信息存储块,SQL文本存储块,查询结果存储块。而第二个查询如 果用的是同一个表,那么最少只需要两个存储块:SQL文本存储块,查询结果存储块。

通过观察 Qcache_queries_in_cache和Qcache_total_blocks可以知道平均每个缓存结果占用的存储块。它们的比例如果接近 1:2,则说明当前的query_cache_min_res_unit参数已经足够大了。如果Qcache_total_blocks比 Qcache_queries_in_cache多很多,则需要增加query_cache_min_res_unit的大小。

Qcache_queries_in_cache*query_cache_min_res_unit(sql 文本和表信息所在的block占用的内存很小,可以忽略)如果远远大于query_cache_size-Qcache_free_memory,那么可 以尝试减小 query_cache_min_res_unit的值。
调整大小
如果Qcache_lowmem_prunes增长迅速,意味着很多缓存因为内存不够而被释放,而不是因为相关表被更新。尝试加大query_cache_size,尽量使Qcache_lowmem_prunes零增长。
启动参数
show variables like 'query_cache%'可以看到这些信息。
query_cache_limit:如果单个查询结果大于这个值,则不Cache
query_cache_size: 分配给QC的内存。如果设为0,则相当于禁用QC。要注意QC必须使用大约40KB来存储它的结构,如果设定小于 40KB,则相当于禁用QC。QC存储的最小单位是1024 byte,所以如果你设定了一个不是1024的倍数的值,这个值会被四舍五入到最接近当前值的等于1024的倍数的值。
query_cache_type:0 完全禁止QC,不受SQL语句控制(另外可能要注意的是,即使这里禁用,上面一个参数所设定的内存大小还是会被分配);1启用QC,可以在SQL语句使用 SQL_NO_CACHE禁用;2可以在SQL语句使用SQL_CACHE启用。
query_cache_min_res_unit:每次给QC结果分配内存的大小
状态
show status like 'Qcache%'可以看到这些信息。
Qcache_free_blocks: 当一个表被更新之后,和它相关的cache blocks将被free。但是这个block依然可能存在队列中,除非是在队列的尾部。这些blocks将会被统计到这个值来。可以用FLUSH QUERY CACHE语句来清空free blocks。
Qcache_free_memory:可用内存,如果很小,考虑增加query_cache_size
Qcache_hits:自mysql进程启动起,cache的命中数量
Qcache_inserts:自mysql进程启动起,被增加进QC的数量
Qcache_lowmem_prunes:由于内存过少而导致QC被删除的条数。加大query_cache_size,尽可能保持这个值0增长。
Qcache_not_cached:自mysql进程启动起,没有被cache的只读查询数量(包括select,show,use,desc等)
Qcache_queries_in_cache:当前被cache的SQL数量
Qcache_total_blocks: 在QC中的blocks数。一个query可能被多个blocks存储,而这几个blocks中的最后一个,未用满的内存将会被释放掉。例如一个QC结果 要占6KB内存,如果query_cache_min_res_unit是4KB,则最后将会生成3个 blocks,第一个block用来存储sql语句文本,这个不会被统计到query+cache_size里,第二个block为4KB,第三个 block为2KB(先allocate4KB,然后释放多余的2KB)。每个表,当第一个和它有关的SQL查询被CACHE的时候,会使用一个 block来存储表信息。也就是说,block会被用在三处地方:表信息,SQL文本,查询结果。

另外一篇:

如 果 MySQL Server 负载比较高,处理非常繁忙的话,可以启动Query Cache 以加速响应时间,启动方法可以在my.cnf(Linux)或my.ini(Windows)中加入不以下项目:(Redhat下面是:/etc /my.cnf;Debian和Ubuntu是在/etc/mysql/my.cnf)

query_cache_size = 268435456
query_cache_type = 1
query_cache_limit = 1048576

以上语句的设置中 query_cache_size 是分配256M内存给Query Cache;query_cache_type=1,是给所有的查询做Cache;query_cache_limit 是指定个别的查询语句1MB的内存。

这些数据可以根据自己的需求作出适当的更改,设置完成之后,保存文档,重新启动MySQL即可。

 

query_cache_type 0 代表不使用缓冲, 1 代表使用缓冲,2 代表根据需要使用。

设置 1 代表缓冲永远有效,如果不需要缓冲,就需要使用如下语句:

SELECT SQL_NO_CACHE * FROM my_table WHERE ...

如果设置为 2 ,需要开启缓冲,可以用如下语句:

SELECT SQL_CACHE * FROM my_table WHERE ...

用 SHOW STATUS 可以查看缓冲的情况:

mysql> show status like 'Qca%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_queries_in_cache | 8 |
| Qcache_inserts | 545875 |
| Qcache_hits | 83951 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2343256 |
| Qcache_free_memory | 33508248 |
| Qcache_free_blocks | 1 |
| Qcache_total_blocks | 18 |
+-------------------------+----------+
8 rows in set (0.00 sec)

如果需要计算命中率,需要知道服务器执行了多少 SELECT 语句:

mysql> show status like 'Com_sel%';
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Com_select | 2889628 |
+---------------+---------+
1 row in set (0.01 sec)

在本例中, MySQL 命中了 2,889,628 条查询中的 83,951 条,而且 INSERT 语句只有 545,875 条。因此,它们两者的和和280万的总查询相比有很大差距,因此,我们知道本例使用的缓冲类型是 2 。

而在类型是 1 的例子中, Qcache_hits 的数值会远远大于 Com_select 。

几个命令:
mysql> show status like 'Qcache%'; #查看mysql查询缓存的运行时状态
mysql> reset query cache;          #重置mysql查询缓存
mysql> flush query cache           #清理查询缓存碎片

时间: 2024-07-30 11:54:56

MySQL的查询缓存的相关文章

MySQL的查询缓存机制基本学习教程_Mysql

MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行相同的sql,服务器直接从缓存中取到结果,而不需要再去解析和执行sql.如果表更改 了,那么使用这个表的所有缓冲查询将不再有效,查询缓存值的相关条目被清空.更改指的是表中任何数据或是结构的改变,包括INSERT.UPDATE. DELETE.TRUNCATE.ALTER TABLE.DROP TABLE或DROP DATABASE等,也包括那些映射到改变了的表的使用MERGE表的查询.显然,这对于频繁更新的表,查询缓存是不适合的,而

mysql 开启查询缓存方法与查询例子

开启缓存,设置缓存大小,具体实施如下: 1.修改配置文件,windows下是my.ini,linux下是my.cnf; 在配置文件的最后追加上:  代码如下 复制代码 query_cache_type = 1 query_cache_size = 600000 需要重启mysql生效: 那么采用第二种方式: b) 开启缓存,两种方式: a)使用mysql命令:  代码如下 复制代码 set global query_cache_type = 1;  set global query_cache_

mysql 设置查询缓存_Mysql

可将如下语句 query_cache_size = 268435456 query_cache_type = 1 query_cache_limit = 1048576 存放到/etc/my.cnf文件的[mysqld]下 然后重启mysql数据库 service mysqld restart 就会启动mysql的缓存机制Query Cache. 在使用中,查询缓存会存储一个 SELECT 查询的文本与被传送到客户端的相应结果. 如果之后接收到一个同样的查询,服务器将从查询缓存中检索结果,而不是

MySQL查询缓存 --《高性能MySQL》读书笔记

        Query Cache(QC)         缓存完整的Select结果,当查询命中该缓存,MySQL会立刻返回结果,跳过解析.优化和执行阶段. 1.如何判断缓存命中         缓存存放在一个引用表中,通过哈希值引用.哈希值包括查询本身.待查数据库.客户端协议版本等可能影响返回结果的信息. 注: 当表被lock tables锁住时,仍可以通过查询缓存返回数据. 任何字符不同(包括空格.注释)都会导致缓存的不命中. 不会被缓存:①查询语句包含不确定数据(如函数now().c

RDS for MySQL查询缓存 (Query Cache) 的设置和使用

功能和适用范围 原理 限制 设置 验证效果 1. 功能和适用范围 功能: 降低 CPU 使用率 降低 IOPS 使用率(某些情况下) 减少查询响应时间,提高系统的吞吐量 适用范围: 表数据修改不频繁.数据较静态 查询(Select)重复度高 查询结果集小于 1 MB 注: 查询缓存并不一定带来性能上的提升,在某些情况下(比如查询数量大,但重复的查询很少)开启查询缓存会带来性能的下降. 2. 原理 RDS for MySQL 对来自客户端的查询(Select)进行 Hash 计算得到该查询的Has

Mysql查询缓存研究

  专家简介    李季鹏 [DBA+社群•开源数据库用户组]联合发起人 5年+MySQL经验,主导运营商去IOE技术落地,精通MySQL数据库及相关解决方案,对MySQL集群架构,高可用方案有深入的研究.       MySQL的查询缓存并非缓存执行计划,而是查询及其结果集,这就意味着只有相同的查询操作才能命中缓存,因此MySQL的查询缓存命中率很低,另一方面,对于大结果集的查询,其查询结果可以从cache中直接读取,有效的提升了查询效率.       1 工作流程和相关参数及命令 1.1 工

mysql缓冲和缓存设置详解_Mysql

MySQL 可调节设置可以应用于整个 mysqld进程,也可以应用于单个客户机会话. 服务器端的设置 每个表都可以表示为磁盘上的一个文件,必须先打开,后读取.为了加快从文件中读取数据的过程,mysqld对这些打开文件进行了缓存,其最大数目由 /etc/mysqld.conf 中的table_cache 指定.清单 4给出了显示与打开表有关的活动的方式. 清单 4. 显示打开表的活动 mysql> SHOW STATUS LIKE 'open%tables'; +---------------+-

Mysql 第十日 字符集,XA事务,查询缓存

字符集和校对 客户端和服务器设置要要保持一致. 校对规则主要是mysql用来比较字符串,比如按照大小写敏感,或者是二进制. 分别对应了cs,ci(不敏感),bin三个对应项 可以指定校对规则对字段排序,但是这样可能会不使用原来的索引. 分布式事务 XA事务需要一个事务协调器来保证所有的事务参与者都完成了准备工作(第一阶段). 都准备好,则提交所有事务(第二阶段). Mysql不能扮演这个协调者,只能是参与节点. 内部XA 平衡多个存储引擎, 以及存储引擎和写二进制日志之间. 如果打开了写二进制日

MySQL 4.1.0 中文参考手册 --- 6.9 MySQL 查询缓存

mysql|参考|参考手册|缓存|中文 MySQL 4.1.0 中文参考手册 --- 犬犬(心帆)翻译 MySQL Reference Manual for version 4.1.0-alpha. 6.9 MySQL 查询缓存 从 MySQL 4.0.1 开始,MySQL server 有一个重要的特征:Query Cache. 当在使用中,查询缓存会存储一个 SELECT 查询的文本与被传送到客户端的相应结果.如果之后接收到一个同样的查询,服务器将从查询缓存中检索结果,而不是再次分析和执行这