MySQL索引

tags: mysql
@烩面 18/04/2025

关于SQL索引

SQL

索引

索引是帮助SQL高效获取数据的有序数据结构

  • 利用索引可以提高数据检索的效率,降低io成本

  • 通过索引对数据进行排序,减少cpu消耗

  • 索引占一部分空间

  • 索引降低了更新表的速度,对表进行插入删除的时候成本提高

索引类型

  • B+树索引
  • Hash索引:底层用哈希表实现,只支持精确匹配不支持范围查询
  • R-Tree空间索引
  • Full-text全文索引

索引结构

InnoDB MYISAM Memory

Q:为什么用B+树不用二叉树,红黑树,B树

A:顺序查找会形成单向链表,性能大大降低,每个节点最多只能存两个子节点,大数据量情况下检索效率低,红黑树在大数据量情况下检索效率也没有提高。而B树无论是叶子节点还是非叶子节点都要保存数据和指针,这样导致一层中能够保存的建值变少,指针跟着减少,要保存大量数据只能增加树的高度,导致性能降低

B+树

非叶子节点为索引,叶子节点存放数据,叶子节点是单向链表

MYSQL的B+树对B+树进行优化,叶子节点形成了双向链表

索引分类

  • 主建索引——只能有一个 PRIMARY,主键索引不能重复,且主键索引不能为空
  • 唯一索引——可以有多个 UNIQUE,唯一索引可以为空,但是不能重复
  • 普通索引——建立在普通字段上的索引,可以重复页,可以为空
  • 前缀索引——对字符类型字段的前几个字符建立的索引,而不是建立在某个字段上的索引,减少索引占用的内存空间
  • 常规索引…
  • 全文索引…

InnoDB索引类型:

  • 聚焦索引:数据和索引在一起,索引的叶子节点保存了行数据——必须有且只有一个
  • 二级索引:数据和索引分开存储,索引结构的叶子节点关联的是对应的主键——可以存在多个
                    InnoDB
             ┌─────────┴─────────┐
             ↓                   ↓
         聚簇索引             二级索引
             │                   │
      通常就是主键索引       name / age / email...
             │                   │
             ↓                   ↓
         整行数据              主键值

二级索引要回表查询,具体过程类似下图:

                查询 name
              二级索引 B+Tree
              找到主键 id
             ┌──────┴──────┐
             ↓             ↓
         需要其他字段     不需要其他字段
             ↓             ↓
          回表          直接返回
       聚簇索引 B+Tree
          完整数据

如果一张表存在主建,主键索引就是聚集索引 如果不存在主键,那么第一个索引UNIQUE为聚集索引 如果不存在主键也没有合适的索引,那么自动生成一个隐藏的rowid作为索引

联合索引

除了上文提到了建立在一个列上的单列索引,有时候会将多个字段组合建立联合索引 使用联合索引的时候,遵循最左匹配原则 也就是说,会先比较在左边的索引,在符合范围的数据内,匹配右边的索引 在这种情况下如果只依靠右边索引查询效率会变低

有一类特殊情况,并不是查询过程使用了联合查询,就代表联合索引中的所有字段都用到了联合查询。这种特殊情况发生在范围查询。范围查询的字段可以使用联合索引,但是在范围查询后面的字段无法使用联合索引,因为范围查询之后的数据不保证有序,此时索引存在的意义不大,只能通过遍历比较这一部分数据来查询匹配项。

索引失效的情况

  1. 左右列模糊匹配
  2. 对索引使用函数
  3. 对索引进行表达式计算
  4. 字符串和数字比较,如果字符串是索引列,会发生隐式类型转换,相当于对索引使用函数
  5. 未满足最左匹配原则
  6. where连接的查询语句中,有一列没有建立索引,也会导致失效

什么情况适合建立索引

  • 字段有唯一性限制
  • 经常用where查询的字段,建立索引可以提高查询速度,如果目标不是一个字段,可以建立联合索引
  • 经常用order by和group by的字段,建立索引的话查询就不需要做排序,因为b+树里面的索引排序好了

什么情况不适合建立索引

  • Where,Orderby,Groupby里面用不到的字段,如果建立索引会占用大量空间
  • 表数据太少的时候也不需要索引
  • 字段中出现大量重复数据,比如性别。MYSQL的优化器在进行优化的时候如果发现某个数据出现重复率很高,会默认不使用索引。
  • 经常更新的字段也不需要建立索引,会导致B+树频繁进行页分裂,指针维护

怎么样对索引进行优化?

  • 前缀索引优化,再进行一些大的字符串索引的时候,可以利用前缀索引,减少索引项的大小。
  • 覆盖索引优化,减少回表查询次数,提高性能
  • 主键索引最好自增,这样方便范围查询,而且加入新数据是插入操作不需要移动数据,性能非常高。如果主键不自增,那么添加的新数据有可能插入现有数据页的某个位置,导致页的复制或者内存碎片
  • 防止索引失效,正确使用最左匹配原则,防止对索引使用函数