高性能Mysql——一条SQL语句执行很慢的原因有哪些?

引入

之前一直没有很详细的讨论这个问题,只是将问题的解决方法归于Explain方法和慢查询日志,这里需要详细的讨论下SQL是如何慢下来的。

SQL变慢,可以大致上分为偶尔执行很慢一直很慢,后一种才是上述解决方法针对的情况,而偶尔很慢实际上可能有很多原因导致。

所以这里分类讨论下两种慢查询的原因。

SQL偶尔执行很慢

一条 SQL 大多数情况正常,偶尔才能出现很慢的情况,针对这种情况,我觉得这条SQL语句的书写本身可能是没什么问题的,而是其他原因导致的,那会是什么原因呢?

数据库在刷新脏页

当我们要往数据库插入一条数据、或者要更新一条数据的时候,我们知道数据库会在内存中把对应字段的数据更新了,但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到 redo log 日记中去,等到空闲的时候,在通过 redo log 里的日记把最新的数据同步到磁盘中去。

实际上,redo log容量是有限的。那么,如果数据库很忙、更新很频繁的情况下,如果redo log写满了,这个时候就没办法等到空闲的时候再把数据同步到磁盘的,只能暂停其他操作,全身心来把数据同步到磁盘中去的,而这个时候,就会导致我们平时正常的SQL语句突然执行的很慢,所以说,数据库在在同步数据到磁盘的时候,就有可能导致我们的SQL语句执行的很慢了。

数据库redo log日志太小,默认单个文件只有50M,3个日志文件循环写,日志的切换也需要花费时间。

数据库缓存过期了

数据库缓存击穿:可能在某一时刻,缓存中的一些重要条目过期,导致大量请求落到MySQL以重新生成缓存条目。

另外,在内部删除缓存算法的效率太低时,MySQL查询缓存有时导致服务由短暂的停顿。

数据库上锁了

我们要执行的这条语句,刚好这条语句涉及到的表,别人在用,并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了。或者,表没有加锁,但要使用到的某个一行被加锁了,这个时候,我也没办法啊。

如果要判断是否真的在等待锁,我们可以用 show processlist这个命令来查看当前的状态。

针对这个问题,也可以理解成为程序设计出了问题,也可能导致SQL语句长期慢查询。

其他原因

其他原因发生的场景比较特殊,这里只做一点简单介绍。

比如:

  1. 从运行得很慢得外部服务来获取数据
  2. DNS查询偶尔会有超时现象
  3. 网络速度慢
  4. 内存不足

SQL一直执行很慢

如果这条 SQL 语句每次都执行的这么慢,那就就要好好考虑下你的 SQL 书写了,下面我们来分析下哪些原因会导致我们的 SQL 语句执行的很不理想。

没有用到索引或者索引失效

  1. 字段没有索引
    刚好你的 c 字段上没有索引,那么抱歉,只能走全表扫描了,你就体验不会索引带来的乐趣了,所以,这回导致这条查询语句很慢。
  2. 字段有索引,但却没有用索引。
    • 出现了运算(不能是表达式的一部分)或者使用了函数。
    • 数据出现了隐式转换
    • 复合索引的情况下,查询条件不满足索引最左的原则
    • 负向查询(not , not in, not like, <>, != ,!>,!< ) 不会使用索引
    • Mysql估计使用索引比全表扫描慢
    • 以%开头的LIKE查询不能够利用B-tree索引

没有用到索引的情况很好想到,那么有没有其他情况导致变慢呢?

查询出的数据量过大

针对这一点,可以理解为:

  1. 查询出来的行很多,可以采用多次查询,其他的方法降低数据量。
  2. 查询出来的列很多,比如返回了不必要的行和列。

硬件问题

比如说IO吞吐量的问题,或者说之前说的内存问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值