MySQL索引解析
文章目录
- 为什么需要索引?
- MySQL索引的底层结构
- 索引的分类
- 按数据结构分类
- 按物理存储分类
- 按字段数量分类
- 联合索引与最左前缀原则
- 索引失效的常见场景
- 1. 函数操作
- 2. 类型转换
- 3. 模糊查询
- 4. 范围查询影响后续字段
- 5. 使用OR连接
- 索引设计原则
- 注意事项
- 1. 不是索引越多越好
- 2. 小表不一定需要索引
- 3. 联合索引的字段顺序很重要
- 4. 注意索引的维护成本
- 总结
为什么需要索引?
数据库索引就像是给数据表建立的"目录",帮助数据库快速定位到需要的数据行。没有索引的查询过程,查询数据走的是全表扫描。有了索引之后,数据库可以通过索引结构快速定位到目标数据,大大减少了需要检查的数据量。
MySQL索引的底层结构
MySQL的InnoDB存储引擎主要使用B+树
作为索引结构,其优点如下:
- 磁盘友好:B+树的节点可以存储更多的键值,减少了树的高度,也就减少了磁盘I/O次数
- 范围查询高效:叶子节点通过指针连接,形成有序链表,范围查询只需要在叶子层遍历
- 稳定的查询性能:所有数据都在叶子节点,查询效率稳定
索引的分类
按数据结构分类
1. B+树索引
最常见的索引类型,适用于大部分查询场景。
2. Hash索引
基于哈希表实现,等值查询速度极快,但不支持范围查询。
3. 全文索引
专门用于文本搜索,支持关键词匹配。
按物理存储分类
1. 聚簇索引(主键索引)
数据行直接存储在索引的叶子节点中,每个表只能有一个聚簇索引。
2. 非聚簇索引(二级索引)
叶子节点存储的是主键值,需要回表查询获取完整数据。
-- 创建表时的聚簇索引
CREATE TABLE user (id INT PRIMARY KEY, -- 聚簇索引name VARCHAR(50),email VARCHAR(100),INDEX idx_name(name) -- 非聚簇索引
);
按字段数量分类
1. 单列索引
CREATE INDEX idx_name ON user(name);
2. 复合索引(联合索引)
CREATE INDEX idx_name_age ON user(name, age);
联合索引与最左前缀原则
复合索引是实际开发中经常用到的优化手段,但需要理解最左前缀原则。
-- 创建复合索引
CREATE INDEX idx_name_age_city ON user(name, age, city);
这个索引实际上相当于创建了三个索引:
- (name)
- (name, age)
- (name, age, city)
能用到索引的查询:
SELECT * FROM user WHERE name = '张三';
SELECT * FROM user WHERE name = '张三' AND age = 25;
SELECT * FROM user WHERE name = '张三' AND age = 25 AND city = '北京';
SELECT * FROM user WHERE name = '张三' AND city = '北京';
不能用到索引的查询:
SELECT * FROM user WHERE age = 25;
SELECT * FROM user WHERE city = '北京';
SELECT * FROM user WHERE age = 25 AND city = '北京';
索引失效的常见场景
在实际开发中,经常会遇到明明创建了索引,但查询还是很慢的情况。以下是一些常见的索引失效场景:
1. 函数操作
-- 索引失效
SELECT * FROM user WHERE YEAR(create_time) = 2023;
2. 类型转换
-- phone字段是VARCHAR类型,索引失效
SELECT * FROM user WHERE phone = 13800138000;-- 正确写法
SELECT * FROM user WHERE phone = '13800138000';
3. 模糊查询
-- 索引失效
SELECT * FROM user WHERE name LIKE '%张%';-- 可以使用索引
SELECT * FROM user WHERE name LIKE '张%';
4. 范围查询影响后续字段
-- 对于复合索引 (name, age, city)
-- age使用了范围查询,city字段的索引会失效
SELECT * FROM user WHERE name = '张三' AND age > 20 AND city = '北京';
5. 使用OR连接
-- 如果OR两边的字段都有索引才能使用索引
SELECT * FROM user WHERE name = '张三' OR email = 'zhangsan@email.com';
索引设计原则
- 选择性高的字段:重复值少的字段更适合创建索引
- 频繁查询的字段:WHERE、ORDER BY、GROUP BY中经常出现的字段
- 小的数据类型:使用更小的数据类型可以减少索引空间
注意事项
1. 不是索引越多越好
每个索引都会占用存储空间,增加写操作的开销。
2. 小表不一定需要索引
对于数据量很小的表(几百条记录),全表扫描可能比索引查询更快。
3. 联合索引的字段顺序很重要
根据查询条件的使用频率和选择性来决定字段顺序。
4. 注意索引的维护成本
频繁的INSERT、UPDATE、DELETE操作会影响索引性能,需要权衡查询性能和写入性能。
总结
索引是数据库性能优化的重要手段,但也不是万能的。要掌握最左前缀原则,合理设计复合索引,避免常见的索引失效场景,在优化方面通过EXPLAIN分析执行计划。