一个 SQL 执行的很慢,两种情况讨论:

1、大多数情况下很正常,偶尔很慢,则有如下原因

(1)、数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘

(2)、执行的时候,遇到锁,如表锁、行锁

2、这条 SQL 语句一直执行的很慢,则有如下原因。

(1)、没有用上索引:例如该字段没有索引;由于对字段进行运算、函数操作导致无法用索引

(2)、数据库选错索引


1.数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘

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

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

2.执行的时候,遇到锁,如表锁、行锁

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

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

3.没有用上索引

  • 字段没有索引
  • 字段有索引,但却没有用索引(有索引却不使用索引的那些情况)

4.数据库选错索引

  • 主键索引和非主键索引是有区别的,主键索引存放的值是整行字段的数据,而非主键索引上存放的值不是整行字段的数据,而且存放主键字段的值。也就是说,我们如果走 c 这个非主键字段的索引的话,最后会查询到对应主键a的值,然后,再根据主键的值走主键索引,查询到整行数据返回。
  • 由于统计的失误,导致系统没有走索引,而是走了全表扫描