慢sql优化

Posted by lily's blog on October 23, 2024

学习文章

  1. 慢查询优化 (yuque.com)
  2. MySQL中什么情况下会出现索引失效?如何排查索引失效?_如何定位索引失效-CSDN博客
  3. 五分钟搞懂MySQL索引下推大家好,我是老三,分享一个小知识点。面试时候问到索引,常常会顺嘴问一句索引下推。给我五分钟, - 掘金 (juejin.cn)
  4. MySQL索引可能失效之or、is null、is not null、不等于(!=,<>)、联合索引_!= 索引不失效-CSDN博客
  5. 优化方式

  6. 先通过explain执行计划检查具体执行情况
  7. 检查是否使用了索引
  8. 避免索引失效的情况
  9. 深分页优化
    1. 内嵌 SELECT 可以更高效地定位到目标数据,避免回表查询,减少了查询开销。

Order By优化

ORDER BY 是一个成本较高的操作,因为排序不仅涉及大量的数据处理,还可能需要创建临时表并进行额外的 I/O 操作。为了更生动地理解它为什么会带来高成本,可以从以下几个方面来说明:

  1. 全字段排序:当我们执行 ORDER BY 时,如果排序字段没有索引,MySQL 需要对所有符合条件的记录进行排序。举个例子,想象一下你有一大堆纸,每张纸上写了一个数字,而这些纸张是乱序的。你需要先找到所有符合条件的纸张(比如数字小于 100),然后将这些纸按从小到大的顺序重新排列。

在数据库中,MySQL 会将这些需要排序的记录放入 sort_buffer(一种内存空间),并在内存中对这些数据进行排序。如果数据量很大,内存不够用,就必须将部分数据写到磁盘,这大大增加了处理时间和资源消耗。

  1. 基于 rowid 的排序:当查询返回的字段不在索引中,MySQL 可能会用 rowid(指向表中具体记录的行号)来进行排序。MySQL 首先会在排序时建立一个临时表,只记录每条记录的 rowid 和排序字段。排序完成后,它需要“回表”——根据 rowid 去主表中找到完整的数据。

举个例子,想象你想根据一个属性(比如年龄)对员工名单排序,但你只拿到了员工的工号(rowid)。你先根据工号把他们的年龄排好序,然后再一一找到对应的员工完整信息。这个过程就是所谓的“回表操作”,它增加了额外的 I/O 开销。

  1. 临时表和 I/O 开销:排序的过程中,尤其是当需要处理大量数据时,MySQL 可能需要创建临时表,临时表的创建与销毁都会消耗资源。此外,排序可能会超过内存限制,将部分数据写到磁盘再读回,进一步增加了时间和硬盘 I/O(输入/输出)成本。

  2. 索引的作用:如果你给 ORDER BY 的字段添加了索引,就像是将一堆无序的纸张提前按顺序排好了放在抽屉里。这样当你需要排序时,MySQL 只需按顺序从这个“有序的抽屉”里拿出数据,而不需要再重新排序。这样就节省了大量的时间和资源。

  3. 组合索引的顺序:当 ORDER BY 涉及多个字段时,索引的设计很关键。如果索引的顺序和 ORDER BY 中字段的顺序一致,MySQL 可以直接利用索引的顺序来进行排序。如果索引顺序不匹配,MySQL 就需要额外排序。

总结:
排序耗时的根本原因是数据量大时,内存和磁盘的I/O开销增加。如果排序的字段有索引,MySQL 可以直接利用这些有序的数据,减少不必要的资源消耗,否则排序会涉及到临时表、回表操作等复杂过程。