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=2、ORDER 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 id、GROUP 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不在索引中)。
四、关键注意事项(避免索引失效)
- 最左前缀原则:联合索引
(a, b, c)仅对a、a+b、a+b+c的查询生效,对b、b+c的查询失效; - 索引列不能参与计算 / 函数:
WHERE id+1=100、WHERE SUBSTR(name, 1, 2)='张'会导致索引失效; - 模糊查询前缀通配符:
WHERE name LIKE '%三'会导致索引失效(LIKE '张%'生效); - 隐式类型转换:
WHERE phone='13800138000'(phone是 INT 类型)会触发类型转换,索引失效; - OR 连接非索引列:
WHERE id=100 OR age=20(age无索引)会导致索引失效。
总结
MySQL 索引的核心是 B + 树结构 + InnoDB 聚簇索引:
- 类型:按功能可分为主键、唯一、普通、联合等,按存储可分为聚簇和非聚簇,按结构以 B + 树为主;
- 结构:B + 树通过 “平衡结构 + 有序叶子链表” 适配磁盘 I/O,兼顾等值和范围查询;
- 存储:InnoDB 聚簇索引(索引 = 数据)是效率核心,非聚簇索引需回表(覆盖索引除外);
- 功能:加速查询、排序、分组,核心是减少磁盘 I/O,避免全表扫描。
实际开发中,需根据业务查询场景选择合适的索引类型(如多列查询用联合索引,长字符串用前缀索引),同时避免索引失效,平衡查询效率和写入性能(索引越多,写入越慢)。