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

1、MySQL查询缓存

很多数据库产品都能够缓存查询的执行计划,对于相同类型的SQL就可以跳过SQL解析和执行计划生成阶段。MySQL还有另一种不同的缓存类型:缓存完整的SELECT查询结果,也就是“查询缓存”。

查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都将失效。

查询缓存对应用程序是完全透明的。应用程序无须关心MySQL是通过查询缓存返回的结果还是实际执行返回的结果。

另外,随着现在的通用服务器越来越强大,查询缓存可能是一个影响服务器扩展性的因素。它可能成为整个服务器的资源竞争单点,在多核服务器上还可能导致服务器僵死。


1.1查询缓存的工作机制

Mysql 判断是否命中缓存的办法很简单,首先会将要缓存的结果放在引用表中,然后使用查询语句,数据库名称,客户端协议的版本等因素算出一个hash值,这个hash值与引用表中的结果相关联。如果在执行查询时,根据一些相关的条件算出的hash值能与引用表中的数据相关联,则表示查询命中

通过have_query_cache服务器系统变量指示查询缓存是否可用:

mysql> SHOW VARIABLES LIKE ‘have_query_cache‘;
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+

为了监视查询缓存性能,使用SHOW STATUS查看缓存状态变量:

mysql> SHOW STATUS LIKE ‘Qcache%‘;
+-------------------------+--------+
|变量名                   |值 |
+-------------------------+--------+
| Qcache_free_blocks      | 36     |
| Qcache_free_memory      | 138488 |
| Qcache_hits             | 79570  |
| Qcache_inserts          | 27087  |
| Qcache_lowmem_prunes    | 3114   |
| Qcache_not_cached       | 22989  |
| Qcache_queries_in_cache | 415    |
| Qcache_total_blocks     | 912    |
+-------------------------+--------+

任何字符的不同,例如空格、注释都会导致缓存的不命中。如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、系统表、或者任何包含列级别权限的表,都不会被缓存。

在检查查询缓存之前,MySQL只做一件事情,就是通过一个大小写不敏感的检查看看SQL语句是不是以SEL开头。

如果查询语句中包含任何不确定函数,那么在查询缓存中不可能找到缓存结果的。


1.2额外的消耗
如果使用查询缓存,在进行读写操作时会带来额外的资源消耗,消耗主要体现在以下几个方面:
·        查询的时候会检查是否命中缓存,这个消耗相对较小
·        如果没有命中查询缓存,MYSQL会判断该查询是否可以被缓存,而且系统中还没有对应的缓存,则会将其结果写入查询缓存。
·        如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。
对于InnoDB而言,事务的一些特性还会限制查询缓存的使用。当在事务A中修改了B表时,因为在事务提交之前,对B表的修改对其他的事务而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事务A提交之前是不可缓存的。如果A事务长时间运行,会严重影响查询缓存的命中率。

查询缓存的空间不要设置的太大。
因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况。

1.3查询缓存如何使用内存

查询缓存是完全存储在内存中的,所以在配置和使用它之前,我们需要先了解它是如何使用内存的。除了查询结果之外,它还需要一些内存专门用来确定哪些内存目前是可用的、哪些是已经用掉的、哪些用来存储数据表和查询结果之前的映射、哪些用来存储查询字符串和查询结果。这些基本的管理维护数据结构大概需要40KB的内存资源,除些之外,MySQL用于查询缓存的内存被分成一个个的数据块,数据块是变长的。

当服务器启动的时候,它先初始化查询缓存需要的内存。这个内存池初始是一个完整的空闲块。当有查询结果需要缓存的时候,MYSQL先从大的空间块中申请一个数据块用于存储结果。这个数据块需要大于参数query_cache_min_re_unit

因为需要先锁住空间块,然后找到合适大小数据块,所以分配内存是一个非常慢的操作。MYSQL尽量避免这个操作的次数。当需要缓存一个查询结果的时候,它先选择一个尽可能小的内存块,然后将结果存入其中Qcache_inserts。如果数据块全部用完,但仍有剩余数据需要存储,那么MYSQL会申请一个新数据块(仍然是尽可能小的数据块)--继续存储结果数据。当查询完成时,如果申请的内存还有剩余,MYSQL会将其释放,并放入空闲内存部分。(这里的分配内存块,并不是通过malloc函数向操作系统申请内存,而是MYSQL初次创建查询缓存的时候一次性申请下来的,并由自己管理一大块内存)

1.4什么情况下查询缓存能发挥作用

1、查询缓存可以降低查询执行的时间,但是却不能减少查询结果传输的网络消耗,如果这个消耗是整个查询过程的主要瓶颈,那么查询缓存的作用也很小。

2、对于那些需要消耗大量资源的查询通常都是非常适合缓存的,对于复杂的SELECT语句都可以使用查询缓存,不过需要注意的是,涉及表上的UPDATE、DELETE、INSERT操作相比SELECT来说要非常少才行。

3、查询缓存命中率:Qcache_hits/(Qcahce_hits+Com_select),查询缓存命中率多大才是好的命中率,需要具体情况具体分析。只要查询缓存带来的效率提升大于查询缓存带来的额外消耗,即使30%的命中率也是值得。另外,缓存了哪些查询也很重要,如果被缓存的查询本身消耗巨大,那么即使缓存命中率低,对系统性能提升仍然是有好处的。

4、任何SELECT语句没有从查询缓存中返回都称为“缓存未命中”,以如下可能:

  • 查询语句无法被缓存,可能因为查询中包含一个不确定的函数,或者查询结果太大而无法缓存。
  • MySQL从未处理这个查询,所以结果也从不曾被缓存过。
  • 虽然之前缓存了查询结果,但由于查询缓存的内存用完了,MYSQL需要删除某些缓存,或者由于数据表被修改导致缓存失效。

如果服务器上有大量缓存缓存未命中,但是实际上绝大查询都被缓存了,那么一定是有如下情况发生:

查询缓存还没有完成预热,即MYSQL还没有机会将查询结果都缓存起来。

查询语句之前从未执行过。如果应用程序不会重复执行一条查询语句,那么即使完成预热仍然会有很多缓存未命中。

缓存失效操作太多,缓存碎片、内存不足、数据修改都会造成缓存失效。可以通过参数Com_*来查看数据修改的情况(包括Com_update,Com_delete等),还可以通过Qcache_lowmem_prunes来查看有多少次失效是由于内存不足导致的。

5、有一个直观的方法能够反映查询缓存是否对系统有好处,推荐一个指标:”命中和写入“的比率,即Qcache_hits和Qcache_inserts的比值。根据经验来看,当这个比值大于3:1时通常查询缓存是有效的,如果能达到10:1最好。

6、通常可以通过观察查询缓存内存的实际使用情况Qcache_free_memory,来确定是否需要缩小或者扩大查询缓存。

1.5配置和维护查询缓存

MYSQL提供了一些参数来控制查询缓存的行为,参数如下

·query_cache_limit

MYSQL能够缓存的最大查询结果,查询结果大于该值时不会被缓存。默认值是1048576(1MB)

如果某个查询的结果超出了这个值,Qcache_not_cached的值会加1,如果某个操作总是超出可以考虑在SQL中加上SQL_NO_CACHE来避免额外的消耗

·query_cache_min_res_unit

查询缓存分配的最小块的大小(字节)。 默认值是4096(4KB)。

·query_cache_size

为缓存查询结果分配的内存的数量,单位是字节,且数值必须是1024的整数倍。默认值是0,即禁用查询缓存。请注意即使query_cache_type设置为0也将分配此数量的内存。

·query_cache_type

设置查询缓存类型。设置GLOBAL值可以设置后面的所有客户端连接的类型。客户端可以设置SESSION值以影响他们自己对查询缓存的使用。下面的表显示了可能的值:


选项


描述


0或OFF


不要缓存或查询结果。请注意这样不会取消分配的查询缓存区。要想取消,你应将query_cache_size设置为0。


1或ON


缓存除了以SELECT SQL_NO_CACHE开头的所有查询结果。


2或DEMAND


只缓存以SELECT SQL_NO_CACHE开头的查询结果。

该变量默认设为ON。

·query_cache_wlock_invalidate

一般情况,当客户端对MyISAM表进行WRITE锁定时,如果查询结果位于查询缓存中,则其它客户端未被锁定,可以对该表进行查询。将该变量设置为1,则可以对表进行WRITE锁定,使查询缓存内所有对该表进行的查询变得非法。这样当锁定生效时,可以强制其它试图访问表的客户端来等待。

1.6减少碎片

没有什么办法能够完全避免碎片,但是选择合适的query_cache_min_res_unit可以帮你减少由碎片导致的内存空间浪费。这个值太小,则浪费的空间更少,但是会导致频繁的内存块申请操作;如果设置得太大,那么碎片会很多。调整合适的值其实是在平衡内存浪费和CPU消耗。可以通过内存实际消耗(query_cache_size_Qcache_free_memory)除以Qcache_queries_in_cahce计算单个查询的平均缓存大小。可以通过Qcahce_free_blocks来观察碎片。

通过FLUSH_QUERY_CAHCE完成碎片整理,这个命令将所有的查询缓存重新排序,并将所有的空闲空间都聚焦到查询缓存的一块区域上。

一个用来分析和配置查询缓存的流程图:

1.7查询缓存的替代方案

MySQL查询缓存工作的原则是:执行查询最快的方式就是不去执行,但是查询仍然需要发送到服务器端,服务器也还需要做一点点工作,如果对于某些查询完全不需要与服务器通信效果会如何呢,这时客户端缓存可以很大程度上分担MySQL服务器的压力。

MySQL重点:《高性能MySQL》读书笔记--索引:http://blog.csdn.net/xifeijian/article/details/20312557

时间: 2024-08-07 08:38:20

《高性能MySQL》读书笔记--查询缓存的相关文章

高性能Mysql读书笔记7.12.1

缓存存放在一个应用表中,通过一个哈希值应用,这个哈希值包括了如下因素,查询本身,当前要查询的数据库,客户端协议的版本等一些其他可能会影响返回结果的信息. 当判断缓存是否命中时,Mysql不会解析,"正规化"或者参数化查询语句,而是直接适用SQL语句和客户端发送过来的其他原始信息.任何字符上的不同,例如空额,注释等都会导致缓存的不命中,所以统一的编码规则是一个好的习惯. 检查缓存的时候并没有解析SQL语句,所以Mysql并不知道查询语句中是否包含不确定函数.在检查缓存之前,Mysql就做

高性能MySQL --- 读书笔记(2) - 2016/8/2

第1章 MySQL架构 MySQL架构与其他数据库服务器大不相同,这使它能够适应广泛的应用.MySQL足够灵活,能适应高要求架构.例如Web应用,同时还适用于嵌入式应用.数据仓库.内容索引和分发软件.高可用的冗余系统.联机事务处理系统OLTP及很多其他应用类型. 为了充分发挥MySQL的性能,顺畅地使用它,就必须理解它的设计.MySQL的灵活性体现在很多方面,它可以再众多硬件平台上良好的配置和运行,还支持多种数据类型.不过MySQL最重要.最不同寻常的特征是它的存储引擎框架,这种架构可以讲查询处

高性能mysql读书笔记(一):Schema与数据类型优化

4.5 加快ALTER TABLE 操作的速度 原理: MySQL 的ALTER TABLE 操作的性能对大表来说是个大问题. MySQL 执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据插入新表,然后删除旧表.这样操作可能需要花费很长时间,如果内存不足而表又很大,而且还有很多索引的情况下尤其如此 特点: 大部分ALTER TABLE 操作将导致MySQL 服务中断 ALTER TABLE 本质是建新结构的表,从旧表插入数据到新表 (SHOW STATUS 显示这个语

第13章 MySQL服务器的状态--高性能MySQL学习笔记

13.1 系统变量 -- 服务器配置变量 MySQL通过SHOW VARIABLES  SQL命令显示许多系统变量. 13.2 状态变量--SHOW STATUS SHOW STATUS 命令会在一个由两列(名称/值)组成的表格里显示服务器状态变量.这些变量都是只读的. SHOW STATUS默认显示会话变量,SHOW GLOBAL STATUS显示全局变量. 也可以从INFORMATION_SCHEMA.GLOBAL_STATUS和INFORMATION_SCHEMA.SESSION_STAT

MySQL 权限和查询缓存

MySQL 权限和查询缓存 ================================================================================ 概述: ================================================================================ MySQL用户和权限管理    1.权限类别 ★用户账号:[email protected] user:账户名称: host:此账户可通过哪

Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 1 -使用FOR XML返回XML结果集

原文:Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 1 -使用FOR XML返回XML结果集 XML 介绍 <CustomersOrders> <Customer custid="1" companyname="Customer NRZBB"> <Order orderid="10692" orderdate="2007-10-03T00:00:00&

Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 2 -使用XQuery 查询XML数据

原文:Querying Microsoft SQL Server 2012 读书笔记:查询和管理XML数据 2 -使用XQuery 查询XML数据 XQuery 是一个浏览/返回XML实例的标准语言. 它比老的只能简单处理节点的XPath表达式更丰富. 你可以同XPath一样使用.或是遍历所有节点,塑造XML实例的返回等. 作为一个查询语言, 你需要一个查询处理引擎. SQL Server 数据库通过XML数据类型方法的T-SQL 语句来处理XQuery. SQL Server 并不支持所有的X

高性能javascript读书笔记(三.DOM 编程1)

第三章DOM Script DOM编程 读书笔记 访问和修改DOM元素 浏览器通常要求DOM实现和JavaScript保持相互独立. <!-- 例如IE中,被称为JScript的JavaScript实现位于库文件jscript.dll中,而DOM实现位于另一个库mshtml.dll(内 部代号Trident).这种分离技术允许其他技术和语言,如VBScript,受益于Trident所提供的DOM功能和渲染功能.Safari使用Webkit的WebCore处理DOM和渲染,具有一个分离的JavaS

mysql query cache 查询缓存

查看本博文,并进行验证(验证结果与博文一致): https://blog.csdn.net/carmazhao/article/details/7088530 mysql默认是开启查询缓存的. 设置查询缓存的内存大小: 查询缓存的命中次数查询: 再执行相同sql4次: 插入数据后: 紧接着执行相同的sql,没有命中查询缓存 插入数据后,第二次执行相同的sql,命中查询缓存 原文地址:https://www.cnblogs.com/hblthink/p/8799229.html

数据库MySQL/mariadb知识点——查询缓存

查询的执行路径 SQL语句 查询缓存 解析器 解析树 预处理 查找最好的查询路径 查询优化SQL语句 执行计划 API调用存储引擎 调用数据,返回结果 缓存SELECT操作或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写. 不需要对SQL语句做任何解析和执行,当然语法解析必须通过在先,直接从Query Cache中获得查询结果,提高查询性能 查询缓存的判断规则,不够智能,