索引分类详解:从四个维度全面理解索引
MySQL索引分类详解:从四个维度全面理解索引
一、引言
MySQL索引是提高数据库查询性能的关键技术,为了更好地理解和使用索引,我们需要从多个维度来认识它。本文将从数据结构、物理存储、字段特性和字段个数这四个角度,全面介绍MySQL索引的分类。
二、按「数据结构」分类
2.1 B+tree索引
特点:
- 最常用的索引类型
- 树形数据结构,多路平衡查找树
- 叶子节点相互链接,适合范围查询
- 非叶子节点只存储索引值
适用场景:
- 等值查询(=)
- 范围查询(>, <, BETWEEN)
- 排序操作(ORDER BY)
- 分组操作(GROUP BY)
2.2 Hash索引
特点:
- 基于哈希表实现
- 只能精确匹配所有列
- 查询复杂度O(1)
- 无法进行范围查询
适用场景:
- 等值查询
- 查询结果高度确定
- 数据量较大但查询频繁
2.3 Full-text索引
特点:
- 全文索引,用于文本搜索
- 支持分词和相关性评分
- 占用空间较大
适用场景:
- 文章内容检索
- 关键词搜索
- 相似度匹配
三、按「物理存储」分类
3.1 聚簇索引(主键索引)
特点:
- 数据行实际存储在索引的叶子页中
- 一个表只能有一个聚簇索引
- 通常是主键索引
- 叶子节点包含所有列数据
示例:
CREATE TABLE users (
id INT PRIMARY KEY, -- 聚簇索引
name VARCHAR(50),
age INT
);
3.2 二级索引(辅助索引)
特点:
- 叶子节点存储主键值
- 需要回表查询完整数据
- 一个表可以有多个二级索引
示例:
CREATE INDEX idx_name ON users(name); -- 二级索引
四、按「字段特性」分类
4.1 主键索引
特点:
- 唯一标识数据行
- 不允许NULL值
- 自动创建聚簇索引
示例:
CREATE TABLE products (
product_id INT PRIMARY KEY, -- 主键索引
name VARCHAR(100)
);
4.2 唯一索引
特点:
- 列值必须唯一
- 允许NULL值
- 可以有多个唯一索引
示例:
CREATE UNIQUE INDEX idx_email ON users(email); -- 唯一索引
4.3 普通索引
特点:
- 最基本的索引类型
- 无特殊限制
- 允许重复值和NULL值
示例:
CREATE INDEX idx_age ON users(age); -- 普通索引
4.4 前缀索引
特点:
- 针对长字符串列的部分建立索引
- 减少索引空间占用
- 可能降低索引选择性
示例:
CREATE INDEX idx_name_prefix ON users(name(10)); -- 前缀索引,使用前10个字符
五、按「字段个数」分类
5.1 单列索引
特点:
- 只包含一个字段
- 适用于单字段查询
示例:
CREATE INDEX idx_single ON users(age); -- 单列索引
5.2 联合索引(复合索引)
特点:
- 包含多个字段
- 遵循最左前缀原则
- 可以覆盖多个查询场景
示例:
CREATE INDEX idx_compound ON users(name, age, city); -- 联合索引
最左前缀原则说明:
- 可以使用(name)
- 可以使用(name, age)
- 可以使用(name, age, city)
- 不能跳过中间字段使用
因此,使用联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。在使用联合索引进行查询的时候,如果不遵循「最左匹配原则」,联合索引会失效,这样就无法利用到索引快速查询的特性了。
比如,如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引:
where a=1;
where a=1 and b=2 and c=3;
where a=1 and b=2;
需要注意的是,因为有查询优化器,所以 a 字段在 where 子句的顺序并不重要。(也就是说where a=1 and b=2;和where b=2 and a=1;是一样的,a 和 b 字段都能利用联合索引)
但是,如果查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:
where b=2;
where c=3;
where b=2 and c=3;
上面这些查询条件之所以会失效,是因为(a, b, c) 联合索引,是先按 a 排序,在 a 相同的情况再按 b 排序,在 b 相同的情况再按 c 排序。所以,b 和 c 是全局无序,局部相对有序的,这样在没有遵循最左匹配原则的情况下,是无法利用到索引的。
联合索引有一些特殊情况,并不是查询过程使用了联合索引查询,就代表联合索引中的所有字段都用到了联合索引进行索引查询,也就是可能存在部分字段用到联合索引的 B+Tree,部分字段没有用到联合索引的 B+Tree 的情况。
这种特殊情况就发生在范围查询。联合索引的最左匹配原则会一直向右匹配直到遇到「范围查询」就会停止匹配。也就是范围查询的字段可以用到联合索引,但是在范围查询字段的后面的字段无法用到联合索引。
六、相关问题
1.联合索引 (a, b,c),where条件是 a=2 and c = 1,能用到联合索引吗?
会用到联合索引,但是只有 a 才能走索引,c 无法走索引,因为不符合最左匹配原则。虽然 c 无法走索引, 但是 c 字段 在 5.6 版本之后,会有索引下推的优化,能减少回表查询的次数。
2.联合索引ABC,现在有个执行语句是A = XXX and C < XXX,索引怎么走
根据最左匹配原则,A可以走联合索引,C不会走联合索引,但是C可以走索引下推
3.联合索引(a,b,c) ,查询条件 where b > xxx and a = x 会生效吗
索引会生效,a 和 b 字段都能利用联合索引,符合联合索引最左匹配原则。
七、索引选择建议
7.1 常见场景的索引选择
-
查询单个记录
- 使用主键索引或唯一索引
- 适合B+tree索引
-
范围查询
- 使用B+tree索引
- 避免使用Hash索引
-
全文检索
- 使用Full-text索引
- 适合文本搜索场景
-
多字段查询
- 考虑创建联合索引
- 注意最左前缀原则
7.2 索引设计原则
-
适度建立索引
- 不是越多越好
- 考虑维护成本
-
针对查询优化
- 根据实际查询需求
- 避免无用索引
-
考虑空间开销
- 合理使用前缀索引
- 避免过多的联合索引
八、总结
通过从数据结构、物理存储、字段特性和字段个数这四个维度来理解MySQL索引,我们可以:
- 更好地理解索引的工作原理
- 根据实际需求选择合适的索引类型
- 优化查询性能
- 合理设计数据库结构
在实际应用中,需要根据具体的业务场景和查询需求,综合考虑这些分类特点,选择最适合的索引方案。