为什么需要索引?

数据库索引就像是给数据表建立的"目录",帮助数据库快速定位到需要的数据行。没有索引的查询过程,查询数据走的是全表扫描。有了索引之后,数据库可以通过索引结构快速定位到目标数据,大大减少了需要检查的数据量。

MySQL索引的底层结构

MySQL的InnoDB存储引擎主要使用B+树作为索引结构,其优点如下:

  1. 磁盘友好:B+树的节点可以存储更多的键值,减少了树的高度,也就减少了磁盘I/O次数
  2. 范围查询高效:叶子节点通过指针连接,形成有序链表,范围查询只需要在叶子层遍历
  3. 稳定的查询性能:所有数据都在叶子节点,查询效率稳定

索引的分类

按数据结构分类

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分析执行计划。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐