Open dccmmtop opened 2 years ago
当查询命中缓存时,立即返回结果。跳过了解析 优化和执行阶段
查询缓存在大部分时候都很鸡肋, 在 5.8 版本已经将查询缓存去掉了
下面几个特性是它鸡肋的证据:
查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都将失效。这种机制效率看起来比较低,因为数据表变化时很有可能对应的查询结果并没有变更,但是这种简单实现代价很小,而这点对于一个非常繁忙的系统来说非常重要。
MySql将查询结果存放在引用表中,通过一个哈希值引用,这个哈希值包含了如下因素,查询本身、要查询得数据库、客户端协议的版本等其他可能会影响返回结果的信息,
判断缓存是否命中时,MySql不会解析、参数化、任何规整查询sql的操作,直接使用客户端发来的原始sql语句。任何字符上的不同,如空格、注释都会导致缓存不被命中。
NOW()
CURRENT_DATE()
CURRENT_USER()
CONNECTION_ID()
如果查询语句中包含任何的不确定函数,那么在查询缓存中是不可 能找到缓存结果的。因为即使之前刚刚执行了这样的查询,结果也不会放在查询缓存中。 MySQL在任何时候只要发现不能被缓存的部分,就会禁止这个查询被缓存。
对InnoDB用户来说,事务的一些特性会限制查询缓存的使用。当一个语句在事务中修改了某个表,MySQL会将这个表的对应的查询缓存都设置失效,而事实上,InnoDB的多版本特性会暂时将这个修改对其他事务屏蔽。在这个事务提交之前,这个表的相关查询是无法被缓存的,所以所有在这个表上面的查询一内部或外部的事务——都只能在该事务提交后才被缓存。因此,长时间运行的事务,会大大降低查询缓存的命中率。
只有当缓存带来的资源节约大于其本身的资源消耗时才会给系统带来性能提升
一个判断查询缓存是否有效的直接数据是命中率,就是使用查询缓存返回结果占总查询的比率。当MySQL接收到一个SELECT查询的时候,要么增加Qcache hits的值,要么增加Com select的值。所以查询缓存命中率可以由如下公式计算:Qcache hits / (Qcache hits+Com select)
不过,查询缓存命中率是一个很难判断的数值。命中率多大才是好的命中率?具体情况要具体分析。只要查询缓存带来的效率提升大于查询缓存带来的额外消耗,即使30%命中率对系统性能提升也有很大好处。另外,缓存了哪些查询也很重要,例如,被缓存的查询本身消耗非常巨大,那么即使缓存命中率非常低,也仍然会对系统性能提升有好处。所以,没有一个简单的规则可以判断查询缓存是否对系统有好处。
即Qcache hits和Qcache inserts的比值。根据经验来看,当这个比值大于3:1时通常查询缓存是有效的,不过这个比率最好能够达到10:1。如果你的应用没有达到这个比率,那么就可以考虑禁用查询缓存了,除非你能够通过精确的计算得知:命中带来的性能提升大于缓存失效的消耗,并且查询缓存并没有成为系统的瓶颈。
每一个应用程序都会有一个“最大缓存空间”,甚至对一些纯读的应用来说也一样。最大缓存空间是能够缓存所有可能查询结果的缓存空间总和。理论上,对多数应用来说, 这个数值都会非常大。而实际上,由于缓存失效的原因,大多数应用最后使用的缓存空间都比预想的要小。即使你配置了足够大的缓存空间,由于不断地失效,导致缓存空间 一直都不会接近“最大缓存空间”
通常可以通过观察查询缓存内存的实际使用情况,来确定是否需要缩小或者扩大查询缓存。如果查询缓存空间长时间都有剩余,那么建议缩小;如果经常由于空间不足而导致查询缓存失效,那么则需要增大查询缓存。不过需要注意,如果查询缓存达到了几十兆 这样的数量级,是有潜在危险的。(这和硬件以及系统压力大小有关)。
由于查询缓存这种鸡肋的特性,MySQL 提供一中按照需求决定是否使用 查询缓存,将决定权交给了用户: 配置文件 my.cnf query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE 关键词时才缓存
query_cache_type=2
show global variables like "%query_cache_type%";
show status like'%Qcache%'; //查看运行的缓存信息
当查询命中缓存时,立即返回结果。跳过了解析 优化和执行阶段
鸡肋
查询缓存在大部分时候都很鸡肋, 在 5.8 版本已经将查询缓存去掉了
下面几个特性是它鸡肋的证据:
什么时候不会被缓存
查询涉及的相关表数据发生变化时
查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都将失效。这种机制效率看起来比较低,因为数据表变化时很有可能对应的查询结果并没有变更,但是这种简单实现代价很小,而这点对于一个非常繁忙的系统来说非常重要。
查询语句任何细微变化时
MySql将查询结果存放在引用表中,通过一个哈希值引用,这个哈希值包含了如下因素,查询本身、要查询得数据库、客户端协议的版本等其他可能会影响返回结果的信息,
判断缓存是否命中时,MySql不会解析、参数化、任何规整查询sql的操作,直接使用客户端发来的原始sql语句。任何字符上的不同,如空格、注释都会导致缓存不被命中。
查询语句中有不确定数据时
NOW()
、CURRENT_DATE()
、CURRENT_USER()
、CONNECTION_ID()
等变化的信息查询结果太大
查询缓存内存用完
查询缓存的缺点
对读和写操作带来额外的消耗
事务对查询缓存的影响
对InnoDB用户来说,事务的一些特性会限制查询缓存的使用。当一个语句在事务中修改了某个表,MySQL会将这个表的对应的查询缓存都设置失效,而事实上,InnoDB的多版本特性会暂时将这个修改对其他事务屏蔽。在这个事务提交之前,这个表的相关查询是无法被缓存的,所以所有在这个表上面的查询一内部或外部的事务——都只能在该事务提交后才被缓存。因此,长时间运行的事务,会大大降低查询缓存的命中率。
缓存对系统的影响
只有当缓存带来的资源节约大于其本身的资源消耗时才会给系统带来性能提升
适合做缓存的查询
命中率的计算
一个判断查询缓存是否有效的直接数据是命中率,就是使用查询缓存返回结果占总查询的比率。当MySQL接收到一个SELECT查询的时候,要么增加Qcache hits的值,要么增加Com select的值。所以查询缓存命中率可以由如下公式计算:Qcache hits / (Qcache hits+Com select)
命中率低不代表性能提升少
不过,查询缓存命中率是一个很难判断的数值。命中率多大才是好的命中率?具体情况要具体分析。只要查询缓存带来的效率提升大于查询缓存带来的额外消耗,即使30%命中率对系统性能提升也有很大好处。另外,缓存了哪些查询也很重要,例如,被缓存的查询本身消耗非常巨大,那么即使缓存命中率非常低,也仍然会对系统性能提升有好处。所以,没有一个简单的规则可以判断查询缓存是否对系统有好处。
命中和写入的比率
即Qcache hits和Qcache inserts的比值。根据经验来看,当这个比值大于3:1时通常查询缓存是有效的,不过这个比率最好能够达到10:1。如果你的应用没有达到这个比率,那么就可以考虑禁用查询缓存了,除非你能够通过精确的计算得知:命中带来的性能提升大于缓存失效的消耗,并且查询缓存并没有成为系统的瓶颈。
缓存失效的一些指标检查
缓存空间的设置和使用
并非越大越好
每一个应用程序都会有一个“最大缓存空间”,甚至对一些纯读的应用来说也一样。最大缓存空间是能够缓存所有可能查询结果的缓存空间总和。理论上,对多数应用来说, 这个数值都会非常大。而实际上,由于缓存失效的原因,大多数应用最后使用的缓存空间都比预想的要小。即使你配置了足够大的缓存空间,由于不断地失效,导致缓存空间 一直都不会接近“最大缓存空间”
设置一个合理值
通常可以通过观察查询缓存内存的实际使用情况,来确定是否需要缩小或者扩大查询缓存。如果查询缓存空间长时间都有剩余,那么建议缩小;如果经常由于空间不足而导致查询缓存失效,那么则需要增大查询缓存。不过需要注意,如果查询缓存达到了几十兆 这样的数量级,是有潜在危险的。(这和硬件以及系统压力大小有关)。
查询缓存的一些配置参数
由于查询缓存这种鸡肋的特性,MySQL 提供一中按照需求决定是否使用 查询缓存,将决定权交给了用户: 配置文件 my.cnf
query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE 关键词时才缓存
查看当前mysql实例是否开启缓存机制
监控查询缓存的命中率:
参考资料