MySQL索引
在MySQL数据库中,索引是提升查询性能的核心机制。本文将从基本分类、数据结构、使用场景到优化策略,全面解析MySQL的七种索引类型及其技术细节。
一、索引类型概览
MySQL支持以下主要索引类型:
1. 普通索引(Normal Index)
- 定义:最基本的索引类型,无唯一性限制,允许重复值和空值。
- 适用场景:频繁查询但无需保证唯一性的列。
- 创建方式:
sql
CREATE INDEX idx_name ON table(column); -- 直接创建
ALTER TABLE table ADD INDEX idx_name(column); -- 修改表结构
2. 唯一索引(Unique Index)
- 定义:索引列值必须唯一,允许存在多个NULL值。
- 与普通索引区别:
特性 | 普通索引 | 唯一索引 |
---|---|---|
值唯一性 | 允许重复 | 必须唯一 |
空值处理 | 允许多个 | 允许多个 |
数据约束 | 无 | 有 |
- 创建方式:
sql
sql
CREATE UNIQUE INDEX idx_name ON table(column);
ALTER TABLE table ADD UNIQUE INDEX idx_name(column); -- 修改表结构
3. 主键索引(Primary Key)
- 定义:特殊的唯一索引,不允许NULL值,每个表仅能存在一个。
- 特点:
- 自动创建聚簇索引(InnoDB引擎)
- 物理存储顺序与索引顺序一致
4. 组合索引(Composite Index)
- 定义:在多个字段上建立的联合索引,遵循最左前缀原则。
- 示例:索引
(A,B,C)
生效场景: WHERE A=1 AND B=2
✅WHERE B=2 AND C=3
❌WHERE A=1 AND C=3
✅(仅A生效)- 优化策略:
- 高频查询字段置左
- 使用覆盖索引减少回表
- 定期使用
EXPLAIN
分析索引命中
5. 全文索引(Full-text Index)
- 定义:基于倒排索引实现的文本搜索索引,支持自然语言和布尔搜索。
- 演进:
- 5.6+:InnoDB支持英文全文索引
- 5.7.6+:内置ngram解析器支持中文分词
- 创建示例:
sql
ALTER TABLE articles ADD FULLTEXT INDEX ft_idx (content) WITH PARSER ngram;
- 查询示例:
sql
SELECT * FROM articles
WHERE MATCH(content) AGAINST('+数据库 -Oracle' IN BOOLEAN MODE);
6. 空间索引(Spatial Index)
- 定义:基于R-tree结构的地理空间索引,支持GIS数据类型(POINT/LINESTRING等)。
- 应用场景:
- 地图应用中查询某半径内的POI
- 物流系统追踪车辆位置
- 城市规划中的区域覆盖分析
- 创建限制:
- 仅MyISAM(5.7前)和InnoDB(5.7+)支持
- 字段必须为GEOMETRY类型
7. 哈希索引(Hash Index)
- 原理:通过哈希函数计算键值的哈希码,实现O(1)时间复杂度查询。
- 特点:
- 仅支持等值查询
- Memory引擎显式支持,InnoDB自适应哈希索引
- 冲突处理:链地址法
- 缺陷:
- 不支持范围查询
- 哈希冲突影响性能
二、索引数据结构剖析
B+Tree索引(默认结构)
- 结构特性:
- 非叶节点仅存储键值(索引分离)
- 叶节点形成双向链表,支持范围查询
- 树高通常3-4层(可支持千万级数据)
- 优势:
- 范围查询效率高
- 排序优化
- 页存储适配磁盘IO
B-Tree vs B+Tree
特性 | B-Tree | B+Tree |
---|---|---|
数据存储位置 | 所有节点 | 仅叶节点 |
叶节点链接 | 无 | 双向链表 |
范围查询效率 | 低 | 高 |
磁盘页利用率 | 较低 | 更高 |
三、索引优化实践指南
1. 组合索引优化
- 字段顺序策略:
- 区分度高的字段置左(cardinality大的列)
- 等值查询字段优先范围查询字段
- 示例优化:
sql
-- 原始查询
SELECT * FROM orders
WHERE region='华东' AND order_date BETWEEN '2024-01-01' AND '2024-03-31';
-- 更优索引:(region, order_date)
2. 索引使用准则
- 较频繁查询的字段适合使用索引
- 唯一性太差的字段不适合单独创建索引
- 更新非常频繁的字段不适合创建索引
3. 索引失效场景
- 隐式类型转换(如字符串列用数字查询)
- 对索引列使用函数(
WHERE YEAR(create_time)=2024
) - 前导模糊查询(
LIKE '%关键字%'
) - 索引列参与运算(
WHERE price+10>100
)
4. 监控与维护
- 使用
SHOW INDEX FROM table
分析索引基数 - 结合EXPLAIN执行计划持续优化
- 定期执行
ANALYZE TABLE
更新统计信息 - 通过慢查询日志定位低效索引
四、索引选择矩阵
查询需求 | 推荐索引类型 |
---|---|
等值查询 | 哈希/唯一索引 |
范围查询 | B+Tree |
文本搜索 | 全文索引 |
空间查询 | R-Tree |
多条件组合查询 | 组合索引 |
五、总结
合理使用索引可使查询性能提升数倍,但需注意:
- 索引不是越多越好,维护成本需权衡
- 新版本特性(如MySQL 8.0的倒序索引、函数索引)需关注