MySQL查询缓存

##前言
很多关系型数据库能够缓存查询的执行计划,对于相同类型的SQL可以跳过SQL解析和执行计划生成阶段。MySQL在某些场景下也可以实现,但是MySQL还有另一种不同的缓存类型:缓存完整的SELECT查询结果,也就是“查询缓存”。

MySQL查询缓存保存查询返回的完整结果。当查询命中该缓存,MySQL会立刻返回结果,跳过了解析,优化和执行阶段。

查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都给失败。这种机制效率低,但实现简单,代价很小,对于非常繁忙的系统来来说非常重要。

##如何命中缓存
MySQL判断缓存名字的方式很简单:缓存存放在一个引用表中,通过一个哈希值引用,这个哈希值包含了如下因素,查询本身,当前要查询的数据库,客户端协议的版本等,还有一些其他可能会影响返回结果的信息。

当判断缓存命中时,MySQL不会解析,或者参数化查询语句,而是直接使用SQL语句和客户端发送过来的其他原始信息。(任何字符上的不同,例如空格,注释都会导致缓存的不命中)。

如果查询中包含任何用户自定义函数,存储函数,用户变量,临时表,mysql库中的系统表,或者任何包含列级别权限的表,都不会被缓存。

##查询缓存带来的问题
MySQL的查询缓存很多时候可以提升性能,在使用的时候,有一些问题需要特别注意。比如查询缓存带来的额外消耗:

  • 读查询在开始之前必须先检查是否命中缓存。
  • 结果存入查询缓存,这会带来额外的系统消耗。
  • 当更新,新增某个表数据的时候,MySQL必须将对应表的所有缓存都设置失效。如果查询缓存非常大或者碎片很多,这个操作会带来很大的系统消耗。

对于InnoDB用户来说,事务的一些特性会限制查询缓存的使用。事实上,InnoDB的MVCC特性会暂时将修改对其他事务屏蔽。在这个事务提交之前,这个表的相关查询无法被缓存,查询缓存只能在事务提交之后缓存。因此,长时间运行的事务,会大大降低查询缓存的命中率。

如果查询缓存使用了大量的内存,缓存失效操作就可能成为一个非常严重的问题瓶颈。因为缓存操作是靠一个全局锁操作保护的,所有需要做该操作的查询都需要等待这个锁,无论是检测是否命中缓存,还是缓存失效检测都需要等待这个全局锁。

##什么情况适合查询缓存
并不是什么情况下查询缓存都会提高性能,缓存和失效都会带来额外的消耗,所以只有当缓存带来的资源节省大于其本身的资源消耗时,才算是给系统带来性能提升。

对于那些需要消耗大量资源的查询通常都是非常适合缓存的。例如一些汇总计算查询,复杂的SELECT语句,多表JOIN后还需要排序和分页的查询,这类查询每次执行消耗都很大,但返回的结果集却很小,非常适合缓存。

##查询缓存命中
查询缓存命中率是一个很难判断的数值。命中率多大才是好的命中率?只要查询缓存带来的效率提升大于查询缓存带来的额外消耗,即使命中率很低对系统性能提升也是有好处的。另外,缓存了哪些查询也很重要,例如,被缓存的查询本身消耗巨大,那么即使命中率非常低,也对系统性能提升有好处。

任何SELECT语句没有从查询缓存中返回都称为“缓存未命中”。缓存未命中可能有如下几种原因:

  • 查询语句无法被缓存,可能是因为查询中包含一个不确定的函数,或者查询结果太大无法缓存。
  • MySQL从未处理过这个查询,所以结果也从未备缓存过。
  • 缓存失效策略把缓存“逐出”了查询缓存。

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

  • 查询缓存还没有完成预热。MySQL还没有机会讲查询结果都缓存起来。
  • 查询语句之前从未被执行。
  • 缓存失效操作太多了(缓存碎片,内存不足,数据修改等)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值