MySQL 中的索引是提高查询性能的重要工具,它通过构建数据结构来加速数据检索。MySQL 支持多种索引类型,每种类型适用于不同的场景。以下是 MySQL 中主要的索引类型及其特点:
1. B-Tree 索引(默认类型)
- 结构:基于平衡多路搜索树(B-Tree),适用于等值查询(
=
)、范围查询(>
、<
、BETWEEN
)、排序(ORDER BY
)和分组(GROUP BY
)。 - 特点:
- 叶子节点存储数据或主键值(InnoDB 的聚簇索引直接存储数据,非聚簇索引存储主键值)。
- 支持前缀匹配(如
LIKE 'abc%'
),但LIKE '%abc'
无法利用索引。 - 适用于多列组合索引(遵循最左前缀原则)。
- 适用场景:全值匹配、范围查询、排序、分组。
- 示例:
CREATE INDEX idx_name ON users(name); -- 单列索引 CREATE INDEX idx_name_age ON users(name, age); -- 组合索引
2. Hash 索引
- 结构:基于哈希表,仅支持等值查询(
=
、IN
),不支持范围查询或排序。 - 特点:
- 查询效率高(O(1) 时间复杂度),但仅适用于内存表(如
MEMORY
引擎)或特定场景(如InnoDB
的自适应哈希索引)。 - 无法避免全表扫描(哈希冲突时需遍历链表)。
- 查询效率高(O(1) 时间复杂度),但仅适用于内存表(如
- 适用场景:等值查询(如缓存场景)。
- 示例:
CREATE TABLE hash_table (id INT,name VARCHAR(100),INDEX USING HASH (name) -- MEMORY 引擎支持 ) ENGINE=MEMORY;
3. Full-Text 索引(全文索引)
- 结构:专为文本搜索设计,支持对
CHAR
、VARCHAR
、TEXT
列进行全文检索。 - 特点:
- 使用倒排索引技术,支持自然语言搜索(
MATCH ... AGAINST
)、布尔模式搜索等。 - 仅适用于
MyISAM
和InnoDB
(MySQL 5.6+)。
- 使用倒排索引技术,支持自然语言搜索(
- 适用场景:文本内容搜索(如博客文章、商品描述)。
- 示例:
CREATE FULLTEXT INDEX idx_content ON articles(content); SELECT * FROM articles WHERE MATCH(content) AGAINST('MySQL 索引');
4. R-Tree 索引(空间索引)
- 结构:基于多维空间数据(如地理坐标),支持空间数据查询(如
MBRContains
、ST_Distance
)。 - 特点:
- 仅适用于
MyISAM
和InnoDB
(MySQL 5.7+)。 - 用于地理信息系统(GIS)或空间数据分析。
- 仅适用于
- 适用场景:地理位置查询(如附近商家、区域范围搜索)。
- 示例:
CREATE SPATIAL INDEX idx_location ON stores(location); -- location 为 GEOMETRY 类型 SELECT * FROM stores WHERE MBRContains(GeomFromText('POLYGON(...)'), location);
5. 前缀索引(Partial Index)
- 结构:对字符串列的前 N 个字符创建索引,节省存储空间。
- 特点:
- 适用于长字符串(如 URL、邮箱),但可能降低选择性(重复值增多)。
- 需合理选择前缀长度(通过
COUNT(DISTINCT LEFT(col, N))
评估)。
- 适用场景:长字符串列的等值查询。
- 示例:
CREATE INDEX idx_email_prefix ON users(email(10)); -- 对 email 前 10 个字符建索引
6. 唯一索引(Unique Index)
- 结构:强制列值唯一(允许
NULL
,但NULL
值不重复)。 - 特点:
- 保证数据唯一性,同时可作为普通索引加速查询。
- 适用于主键(
PRIMARY KEY
)或唯一约束(UNIQUE KEY
)。
- 适用场景:需要唯一性的字段(如用户名、身份证号)。
- 示例:
CREATE UNIQUE INDEX idx_username ON users(username); -- 或直接定义唯一约束 ALTER TABLE users ADD CONSTRAINT uk_email UNIQUE (email);
7. 主键索引(Primary Key Index)
- 结构:特殊的唯一索引,不允许
NULL
值,且每张表只能有一个。 - 特点:
- 在 InnoDB 中,主键索引是聚簇索引(数据按主键顺序存储)。
- 用于标识行数据,是表的核心索引。
- 适用场景:表的唯一标识符(如自增 ID、UUID)。
- 示例:
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) );
8. 复合索引(Multi-Column Index)
- 结构:在多列上创建的索引,遵循最左前缀原则。
- 特点:
- 查询需从索引的最左列开始匹配(如
(a,b,c)
索引可加速a
、a,b
、a,b,c
的查询)。 - 避免“索引失效”问题(如跳过最左列或使用范围查询后无法利用后续列)。
- 查询需从索引的最左列开始匹配(如
- 适用场景:多列联合查询(如姓名+年龄筛选)。
- 示例:
CREATE INDEX idx_name_age ON users(name, age); -- 有效查询: SELECT * FROM users WHERE name = 'Alice' AND age = 25; -- 无效查询(跳过最左列): SELECT * FROM users WHERE age = 25;
9. 自适应哈希索引(Adaptive Hash Index, AHI)
- 结构:InnoDB 自动为频繁访问的索引页构建哈希索引,无需手动创建。
- 特点:
- 仅在内存中维护,适用于等值查询(如
=
、IN
)。 - 无法手动控制,由 InnoDB 引擎自动管理。
- 仅在内存中维护,适用于等值查询(如
- 适用场景:高并发等值查询的热点数据。
10. 函数索引(虚拟列索引)
- 结构:对计算列(如
LOWER(name)
)创建索引,避免在查询中重复计算。 - 特点:
- 需 MySQL 5.7+ 或 MariaDB 支持。
- 适用于表达式查询(如不区分大小写的搜索)。
- 示例:
ALTER TABLE users ADD COLUMN name_lower VARCHAR(100) AS (LOWER(name)) STORED; CREATE INDEX idx_name_lower ON users(name_lower); SELECT * FROM users WHERE name_lower = 'alice';
索引选择建议
- 优先选择 B-Tree 索引:适用于大多数场景(等值、范围、排序)。
- 避免过度索引:每个索引会增加写入开销(
INSERT
/UPDATE
/DELETE
)。 - 利用最左前缀原则:设计复合索引时,将高选择性列放在左侧。
- 监控索引使用情况:通过
EXPLAIN
分析查询计划,删除未使用的索引。
总结
索引类型 | 适用场景 | 引擎支持 | 示例 |
---|---|---|---|
B-Tree | 全值、范围、排序、分组 | MyISAM、InnoDB | CREATE INDEX idx ON t(col); |
Hash | 等值查询(内存表) | MEMORY、InnoDB(AHI) | INDEX USING HASH (col) |
Full-Text | 文本搜索 | MyISAM、InnoDB | CREATE FULLTEXT INDEX ... |
R-Tree | 空间数据查询 | MyISAM、InnoDB | CREATE SPATIAL INDEX ... |
前缀索引 | 长字符串列的等值查询 | MyISAM、InnoDB | INDEX (col(10)) |
唯一索引 | 唯一性约束 | 所有引擎 | CREATE UNIQUE INDEX ... |
主键索引 | 表的唯一标识符 | 所有引擎 | PRIMARY KEY (col) |
复合索引 | 多列联合查询 | MyISAM、InnoDB | INDEX (a, b, c) |
根据实际查询需求选择合适的索引类型,并通过 EXPLAIN
验证优化效果。
我正在程序员刷题神器面试鸭上高效准备面试,9000+ 高频面试真题、800 万字优质题解,覆盖主流编程方向,跟我一起刷原题、过面试:点击进入