Skip to content

MySQL 索引的定义

约 1237 字大约 4 分钟

MySQL字节

2025-03-20

⭐ 题目日期:

字节 - 2024/12/10

📝 题解:

MySQL 索引是数据库中用于 加速数据检索 的一种数据结构,通过建立数据的特定映射关系,减少查询时需要扫描的数据量。以下是 MySQL 索引的核心定义、类型、实现机制及使用建议:


一、索引的核心定义

  1. 本质: 索引是一种 有序的数据结构(如 B+树、哈希表),存储表中某列(或列组合)的值及其对应数据的物理地址(如主键值或行指针)。
  2. 作用
    • 加速查询:避免全表扫描,快速定位目标数据。
    • 约束数据:唯一索引(Unique Index)保证列值的唯一性。
  3. 代价
    • 存储空间:索引需要额外存储。
    • 维护成本:数据增删改时需同步更新索引。

二、索引的类型

1. 按数据结构分类

索引类型数据结构特点
B+Tree 索引B+树MySQL 默认索引,支持全值匹配、范围查询、排序和分组。适合高基数(唯一值多)字段。
哈希索引哈希表仅支持等值查询(如 =IN),不支持排序和范围查询。适合内存表(MEMORY引擎)。
全文索引倒排索引用于文本内容的全文搜索(MATCH ... AGAINST),支持关键词匹配。
空间索引R-Tree支持地理空间数据类型(如 GEOMETRY),用于范围查询和空间关系判断。

2. 按功能分类

索引类型特点
主键索引唯一标识每行数据,不允许 NULL 值,一张表只能有一个。
唯一索引确保列值唯一,允许 NULL 值(但只能有一个 NULL)。
普通索引无唯一性约束,仅加速查询。
联合索引基于多列组合的索引,遵循 最左前缀原则
覆盖索引索引包含查询所需的所有字段,无需回表查询数据行。

三、B+Tree 索引的底层实现

1. B+树结构

  • 非叶子节点:存储键值(索引列值)和子节点指针,不存储数据。
  • 叶子节点:存储键值和数据指针(主键值或行数据地址),叶子节点通过指针形成有序链表。
  • 平衡性:所有叶子节点位于同一层,保证查询效率稳定(时间复杂度 O(log N))。

2. 优势

  • 范围查询高效:叶子节点链表支持快速范围扫描(如 WHERE id > 100)。
  • 减少磁盘 I/O:树的高度低,减少磁盘访问次数(节点大小通常与磁盘页对齐)。
  • 排序优化:索引本身有序,避免 ORDER BY 的额外排序开销。

四、索引的创建与管理

1. 创建索引

-- 创建普通索引
CREATE INDEX idx_name ON table_name (column1, column2);

-- 创建唯一索引
CREATE UNIQUE INDEX idx_unique_email ON users (email);

-- 创建主键索引(通常在建表时指定)
ALTER TABLE table_name ADD PRIMARY KEY (id);

2. 查看索引

SHOW INDEX FROM table_name;

3. 删除索引

DROP INDEX idx_name ON table_name;

五、索引的使用原则

1. 适合创建索引的场景

  • 高频查询字段:如 WHEREJOINORDER BYGROUP BY 涉及的列。
  • 高区分度列:列值的唯一性高(如用户ID、手机号)。
  • 联合索引优化:根据查询条件组合多列,注意最左前缀原则。

2. 避免无效索引

  • 低区分度列:如性别(只有男/女)不适合单独建索引。
  • 频繁更新的列:维护索引的代价可能超过查询收益。
  • 过长的字段:如 TEXT 类型,应使用前缀索引(INDEX (column(10)))。

3. 索引失效的常见原因

  • 违反最左前缀原则:联合索引未从最左列开始使用。
  • 对索引列运算或函数:如 WHERE YEAR(create_time) = 2023
  • 隐式类型转换:如字符串列使用数字查询 WHERE id = '100'
  • OR 连接非索引列:如 WHERE a=1 OR b=2(若 b 无索引,全表扫描)。

六、示例与最佳实践

1. 联合索引的最左前缀原则

  • 索引定义INDEX (a, b, c)

  • 有效查询

    WHERE a = 1; 
    WHERE a = 1 AND b = 2; 
    WHERE a = 1 AND b = 2 AND c = 3;
    WHERE a = 1 ORDER BY b, c;
  • 无效查询

    WHERE b = 2;              -- 未使用 a
    WHERE a = 1 AND c = 3;    -- 跳过 b

2. 覆盖索引优化

  • 查询SELECT name FROM users WHERE age = 25;
  • 索引CREATE INDEX idx_age_name ON users (age, name);
    • 索引包含所有查询字段,无需回表。

七、总结

MySQL 索引通过 B+树 等数据结构加速数据检索,核心要点包括:

  1. 索引类型:B+Tree(默认)、哈希、全文、空间索引。
  2. 使用原则:高频查询字段、高区分度列、避免冗余索引。
  3. 优化方向:覆盖索引、联合索引最左前缀、减少索引失效场景。

合理使用索引可显著提升查询性能,但需平衡存储成本与维护开销。