一、为什么需要索引?
先看一个问题。
假设用户表:
CREATE TABLE user( id BIGINT, username VARCHAR(50), age INT );数据:
id username age 1 Tom 20 2 Jack 25 3 Lucy 18 ... 10000000 Mike 30现在执行:
SELECT * FROM user WHERE username='Tom';没有索引时
MySQL 怎么查?
只能:
第一条 ↓ 第二条 ↓ 第三条 ↓ ... ↓ 1000万条这种方式叫:
全表扫描(Full Table Scan)
时间复杂度:
O(n)数据越多:
越慢。
有索引时
例如:
给 username 创建索引:
CREATE INDEX idx_username ON user(username);MySQL 会建立类似:
索引结构 Tom | 位置 | 数据行查询:
WHERE username='Tom'可以快速定位。
时间复杂度:
O(log n)二、什么是索引?
定义:
索引是数据库为了提高查询效率而创建的一种数据结构。
简单理解:
索引 = 数据目录。
现实例子:
没有目录的书:
找 MySQL章节 翻第一页 翻第二页 ... 翻500页有目录:
目录 MySQL ↓ 第300页快速定位。
数据库索引也是类似思想。
三、MySQL 常见索引类型
1. 普通索引(普通查询)
语法:
CREATE INDEX idx_name ON user(name);作用:
提高查询速度。
2. 唯一索引
保证数据唯一。
例如:
手机号:
CREATE UNIQUE INDEX idx_phone ON user(phone);保证:
13800000001不能重复。
3. 主键索引
创建主键:
PRIMARY KEY(id)MySQL 自动创建索引。
例如:
id BIGINT PRIMARY KEY4. 联合索引 ⭐⭐⭐⭐⭐
多个字段组成索引。
例如:
CREATE INDEX idx_name_age ON user(name, age);表示:
同时根据:
name + age建立索引。
四、索引的数据结构
MySQL 常用:
B+Tree
这是重点。
为什么不用:
- 数组?
- 链表?
- 二叉树?
而选择:
B+Tree?
1. 数组
查询:
快:
O(1)但是:
插入删除慢。
2. 链表
查询:
慢:
O(n)3. 二叉树
如果数据:
1 \ 2 \ 3 \ 4会退化成链表。
4. B+Tree
结构:
50 / \ 20 80 / \ / \ 10 30 60 90 数据存储在叶子节点特点:
- 高度低
- 查询快
- 适合磁盘
- 范围查询优秀
所以 MySQL InnoDB 使用 B+Tree。
五、索引创建和删除
创建
CREATE INDEX idx_user_name ON user(username);查看索引
SHOW INDEX FROM user;删除索引
DROP INDEX idx_user_name ON user;六、什么时候应该创建索引?
适合:
1. 经常查询字段
例如:
WHERE username='Tom'2. 经常排序
例如:
ORDER BY create_time DESC3. 经常关联
例如:
JOIN user ON order.user_id=user.id4. 外键字段
例如:
order.user_id七、索引是不是越多越好?
不是。
这是面试高频问题。
原因:
① 占用空间
索引也是数据。
例如:
10GB数据 + 多个索引 可能增加几GB② 降低写入速度
INSERT:
原来:
写数据有索引:
写数据 + 更新索引UPDATE:
修改字段:
可能需要更新索引。
DELETE:
删除数据:
同时删除索引记录。
所以:
索引提高查询速度,但是降低写入性能。
八、本节总结
| 内容 | 说明 |
|---|---|
| 索引 | 提高查询速度的数据结构 |
| 无索引 | 全表扫描 |
| 有索引 | 快速定位 |
| MySQL索引结构 | B+Tree |
| 主键 | 自动创建索引 |
| 唯一索引 | 保证唯一 |
| 联合索引 | 多字段索引 |
| 索引缺点 | 占空间、降低写性能 |
🎯 本节核心一句话:
索引就是数据库的数据目录,通过空间换时间,让查询从扫描大量数据变成快速定位数据。