跳过正文
  1. 全部/
  2. 笔记/
  3. 面试/
  4. 数据库/
  5. MySQL/

3 索引

目录
  1. 索引本质上是一种帮助数据库快速查询数据的数据结构,MySQL InnoDB 默认使用 B+Tree 实现索引。
  2. 有了索引后,数据库不需要全表扫描,而是可以快速定位数据位置,从而提高查询效率。
  3. 不过索引也有代价,会占用额外空间,并且会降低 INSERT、UPDATE、DELETE 的性能,因为写数据时还需要维护索引结构。

结构
#

索引的就是帮助存储引擎快速获取数据的一种数据结构 InnoDB 是在 MySQL 5.5 之后成为默认的 MySQL 存储引擎,B+Tree 索引类型也是 MySQL 存储引擎采用最多的索引类型。

Pasted image 20260317120849.png

B+ Tree 索引优势
#

B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。

  1. B树: 叶子节点不存放数据,相比之下 B+ Tree IO次数少,可以范围查找
  2. 二叉树:IO次数多
  3. Hash:不能范围查找

分类
#

分类1: 主键索引:唯一不空 唯一索引:唯一 常规索引:无限制 前缀索引:指对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引

分类2

聚集索引(主键索引):

  • 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
  • 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key);
  • 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key);

二级索引:

  • 回表查询」,也就是说要查两个 B+ Tree 才能查到数据
  • 二级索引的 B+ Tree 就能查询到结果的过程就叫作「覆盖索引」,也就是只需要查一个 B+ Tree 就能找到数据。

分类3: 单列索引 联合索引:使用联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。在使用联合索引进行查询的时候,如果不遵循「最左匹配原则」,联合索引会失效,这样就无法利用到索引快速查询的特性了。

SQL 性能分析
#

查看执行频次 慢查询日志 show profiles explain:

  • type:
    • All(全表扫描);
    • index(全索引扫描);
    • range(索引范围扫描);
    • ref(非唯一索引扫描);
    • eq_ref(唯一索引扫描);
    • const(结果只有一条的主键或唯一索引扫描)。

联合索引使用原则
#

最左匹配原则

  • 使用联合索引的时候,要逐个索引依次匹配
  • 若是前一个使用范围查询,下一个就不能使用索引了
  • 小于等于的时候=是可以用下一个索引

索引下推:可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

提高条件过滤效率 利用覆盖索引避免回表

索引优化
#

  1. 前缀索引优化:使用某个字段中字符串的前几个字符建立索引
  2. 覆盖索引优化:覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。
  3. 主键索引自增
  4. 索引NOT NULL

Count()
#

count(*) = count(1) > count(主键) > count(字段)

count(1)、 count(*)、 count(主键字段)在执行的时候,如果表里存在二级索引,优化器就会选择二级索引进行扫描。

count(字段)会采用全表扫描的方式来统计。

Mysql分页性能优化
#

MySQL 分页在 offset 很大时性能会很差,因为 MySQL 需要先扫描并丢弃前面的记录。
如果涉及回表,还会产生大量随机 IO。
优化方法包括:

  • 使用覆盖索引减少回表
  • 使用子查询或延迟关联优化分页
  • 使用基于游标(where id > xxx)的方式避免大 offset
  • 避免无索引排序

索引失效
#

今天给大家介绍了 6 种会发生索引失效的情况:

  1. 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
  2. 当我们在查询条件中对索引列使用函数,就会导致索引失效。
  3. 当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
  4. MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
  5. 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
  6. 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
Reply by Email