mysql的索引

90 阅读9分钟

MySQL 的索引是提升查询效率的核心机制,本质是基于特定数据结构构建的 “数据字典” ,用于快速定位表中的数据行,避免全表扫描。其设计围绕 “查询提速” 展开,同时需平衡存储开销和写入性能。以下从 索引类型、底层结构、存储方式与核心功能 三方面详细解析:

一、MySQL 索引的类型(按不同维度分类)

索引可从「数据结构」「物理存储」「功能逻辑」三个核心维度分类,不同类型对应不同使用场景:

1. 按「数据结构」分类(底层实现)

这是索引的核心分类,决定了查询效率和适用场景:

索引类型底层结构适用场景优点缺点
B + 树索引B + 树(平衡多路查找树)等值查询、范围查询(>、<、BETWEEN)、排序1. 平衡树结构,查询时间稳定(O (log n));2. 叶子节点有序且链表连接,支持范围查询和排序;3. 非叶子节点仅存索引键,内存利用率高不适合高基数(重复值少)的等值查询(不如哈希)
哈希索引哈希表(键值对映射)等值查询(=、IN)等值查询极快(O (1)),直接通过哈希值定位1. 不支持范围查询、排序;2. 哈希冲突会导致性能下降;3. MySQL 仅 Memory 引擎支持,InnoDB 仅自适应哈希索引(AHI,自动生成)
全文索引倒排索引(词项 - 文档映射)文本模糊查询(MATCH AGAINST,如文章关键词搜索)支持自然语言搜索,比 LIKE '%关键词%' 高效1. 仅支持 CHAR、VARCHAR、TEXT 类型;2. 对短文本、高频词效率低
R 树索引R 树(空间数据结构)空间数据查询(如地理坐标、矩形范围)高效处理空间关系查询(如距离、包含)仅支持 MyISAM/InnoDB 5.7+,适用场景有限

核心结论:B + 树索引是 MySQL 最核心、最常用的索引(InnoDB/MyISAM 均默认支持),其他索引仅用于特殊场景。

2. 按「物理存储」分类(索引与数据的存储关系)

该分类仅针对 InnoDB 引擎(MyISAM 无聚簇索引概念),直接影响查询效率(是否需要 “回表”):

索引类型存储方式核心特点示例
聚簇索引(Clustered Index)索引与数据存储在一起,索引的叶子节点直接存储整行数据1. 一张表仅能有 1 个聚簇索引;2. 查询时无需回表,效率极高;3. InnoDB 中,主键索引默认是聚簇索引主键 id 索引,叶子节点存 id、name、age 等整行数据
非聚簇索引(Secondary Index)索引与数据分开存储,索引的叶子节点仅存储「主键值」(而非整行数据)1. 一张表可有多非聚簇索引;2. 查询时需通过主键值回聚簇索引查整行数据(“回表”);3. 也叫 “二级索引”“辅助索引”普通索引 name,叶子节点存 name + 对应 id

关键:InnoDB 的聚簇索引是查询效率的核心,主键查询无需回表,而非聚簇索引需回表(除非是 “覆盖索引”,见下文功能部分)。

3. 按「功能逻辑」分类(业务使用场景)

这是开发中最常接触的分类,基于索引的业务用途划分:

索引类型功能描述约束与注意事项适用场景
主键索引(Primary Key)唯一标识表中每行数据,默认是聚簇索引1. 唯一且非空(UNIQUE + NOT NULL);2. 一张表仅 1 个表的唯一标识(如用户 id、订单 order_id
唯一索引(Unique Index)保证索引列的值唯一(允许 NULL,但最多 1 个)1. 避免重复数据;2. 可作为聚簇索引(无主键时)唯一字段(如手机号 phone、身份证号 id_card
普通索引(Normal Index)无约束条件,仅用于加速查询1. 允许重复值、NULL;2. 最常用的索引类型高频查询字段(如商品 category_id、用户 age
联合索引(Composite Index)多列组合而成的索引(如 (a, b, c)1. 遵循 “最左前缀原则”(查询需包含左列才生效);2. 可覆盖多列查询多列联合查询(如 WHERE a=1 AND b=2ORDER BY a, b
前缀索引(Prefix Index)仅对字符串字段的前 N 个字符建立索引1. 减少索引存储开销;2. 不支持覆盖索引(无法通过前缀索引获取完整字段)长字符串字段(如 email 取前 10 位、address 取前 20 位)
空间索引(Spatial Index)基于空间数据结构(R 树),用于地理信息查询仅支持空间类型字段(如 GEOMETRY、POINT地理坐标查询(如 “附近的商家”)

二、MySQL 索引的底层结构(核心:B + 树详解)

MySQL 中绝大多数索引(主键、唯一、普通、联合)的底层都是 B + 树,其结构设计专为磁盘存储和查询优化:

1. B + 树的结构特点

B + 树是「平衡多路查找树」,结构分为三层,核心优化是 “适配磁盘 I/O 特性”(磁盘读取按 “页”(默认 16KB)为单位,B + 树能让一次查询仅需 3-4 次磁盘 I/O):

  • 根节点:最顶层节点,存储索引键和指向子节点的指针(无数据);
  • 非叶子节点:中间层节点,仅存储索引键和指针(不存数据),用于快速定位到叶子节点;
  • 叶子节点:最底层节点,存储索引键和对应数据(聚簇索引存整行数据,非聚簇索引存主键),且所有叶子节点通过「双向链表」连接。

2. B + 树的核心优势(为何成为默认索引结构)

  • 查询效率稳定:平衡树结构,无论查询哪个数据,都需遍历从根到叶子的路径(高度通常 3-4 层),时间复杂度 O (log n);
  • 支持范围查询和排序:叶子节点链表有序,范围查询(如 id BETWEEN 100 AND 200)只需遍历链表,无需回溯;
  • 内存利用率高:非叶子节点仅存索引键和指针,单个节点可存储更多索引项,减少磁盘 I/O 次数;
  • 适配磁盘存储:节点大小默认等于磁盘页(16KB),一次 I/O 可加载整个节点,提升读取效率。

3. 其他结构补充

  • 哈希索引:底层是哈希表,键为索引列值,值为数据行地址。等值查询(WHERE phone='13800138000')直接通过哈希计算定位,比 B + 树快,但无法处理范围查询(phone > '13800138000');
  • 全文索引:底层是「倒排索引」,将文本拆分为 “词项”(如 “MySQL 索引优化” 拆分为 “MySQL”“索引”“优化”),存储词项与文档(数据行)的映射关系,支持关键词搜索;
  • R 树索引:专为空间数据设计,将空间对象(如坐标、矩形)组织为树结构,支持 “包含”“相交”“距离” 等空间查询。

三、索引的存储方式与核心功能

1. 索引的存储差异(InnoDB vs MyISAM)

MySQL 索引的存储方式与存储引擎强相关,核心差异在「聚簇索引」和「数据与索引的分离」:

存储引擎聚簇索引索引与数据存储关系主键索引特点非聚簇索引特点
InnoDB支持(默认主键)聚簇索引:索引 = 数据;非聚簇索引:索引与数据分离叶子节点存整行数据叶子节点存主键值(需回表)
MyISAM不支持索引与数据完全分离(索引文件 .MYI,数据文件 .MYD叶子节点存数据行地址叶子节点存数据行地址(无需回表,但无聚簇索引优势)

关键结论:InnoDB 的查询效率通常高于 MyISAM,核心原因是聚簇索引无需回表,而 MyISAM 所有索引都需通过地址查找数据。

2. 索引的核心功能(解决什么问题)

索引的核心价值是「加速数据访问」,具体体现在 4 个场景:

  • 加速等值查询:通过索引快速定位匹配条件的行(如 WHERE id=100 走主键索引,直接定位);
  • 加速范围查询:B + 树叶子节点有序,范围查询(WHERE age BETWEEN 18 AND 30)无需全表扫描,仅遍历链表;
  • 加速排序和分组:若排序 / 分组字段是索引列(如 ORDER BY idGROUP BY category_id),可直接利用索引的有序性,避免 “文件排序”(性能极低);
  • 覆盖查询(避免回表) :若查询的列都包含在非聚簇索引中(如联合索引 (a, b, c),查询 SELECT a, b, c WHERE a=1),无需回聚簇索引查整行数据,直接返回索引中的数据,效率接近聚簇索引。

示例:联合索引 (name, age),查询 SELECT name, age WHERE name='张三' 是覆盖查询,无需回表;若查询 SELECT name, age, address,则需回表(address 不在索引中)。

四、关键注意事项(避免索引失效)

  1. 最左前缀原则:联合索引 (a, b, c) 仅对 aa+ba+b+c 的查询生效,对 bb+c 的查询失效;
  2. 索引列不能参与计算 / 函数WHERE id+1=100WHERE SUBSTR(name, 1, 2)='张' 会导致索引失效;
  3. 模糊查询前缀通配符WHERE name LIKE '%三' 会导致索引失效(LIKE '张%' 生效);
  4. 隐式类型转换WHERE phone='13800138000'phone 是 INT 类型)会触发类型转换,索引失效;
  5. OR 连接非索引列WHERE id=100 OR age=20age 无索引)会导致索引失效。

总结

MySQL 索引的核心是 B + 树结构 + InnoDB 聚簇索引

  • 类型:按功能可分为主键、唯一、普通、联合等,按存储可分为聚簇和非聚簇,按结构以 B + 树为主;
  • 结构:B + 树通过 “平衡结构 + 有序叶子链表” 适配磁盘 I/O,兼顾等值和范围查询;
  • 存储:InnoDB 聚簇索引(索引 = 数据)是效率核心,非聚簇索引需回表(覆盖索引除外);
  • 功能:加速查询、排序、分组,核心是减少磁盘 I/O,避免全表扫描。

实际开发中,需根据业务查询场景选择合适的索引类型(如多列查询用联合索引,长字符串用前缀索引),同时避免索引失效,平衡查询效率和写入性能(索引越多,写入越慢)。