MySQL 索引入门(InnoDB 视角)
1. 为什么要使用索引
使用索引的核心目标是提升查询性能,主要有以下几点:
- 减少磁盘 I/O(使用高效数据结构,更快定位目标页)
- 减少扫描行数(降低 CPU 过滤成本)
- 支持高效排序 / 分组 / 范围查询
2. 索引的代价与注意点
索引有明显收益,但也有代价:
- 占用额外存储空间(需要保存额外索引结构)
INSERT / UPDATE / DELETE变慢(需要维护索引)- 索引过多会增加优化器决策与维护成本
注意:表上有索引,不代表 SQL 一定会用索引。比如小表(几百行)全表扫描可能更优。
3. InnoDB 存储引擎(MySQL 默认)
3.1 使用的数据结构
InnoDB 使用 B+Tree 。其存储单位是页(Page) ,默认页大小通常为 16KB,本质是由页组成的多叉树。
- 非叶子节点:存储
键值 + 子页指针,用于导航 - 叶子节点:存储真正数据项
- 聚簇索引叶子页:存整行记录
- 二级索引叶子页:存索引列 + 主键值
- 叶子页之间有双向链表:支持范围查询和顺序扫描
3.2 对比其他数据结构
- B 树 vs B+ 树 :B+ 树是 B 树的改进版本,针对范围查询、
ORDER BY、JOIN等场景更友好。 - MySQL 常用 B+ 树;MongoDB 常见实现与场景不同,偏文档模型与点查负载,具体取决于引擎实现与业务模式。
3.3 InnoDB 索引模型
-
聚簇索引(Clustered Index)
- 叶子节点存整行数据
- 表数据本身按该索引组织
- 可理解为:主键 B+Tree 与数据组织在一起
-
二级索引(Secondary Index)
- 叶子节点存
二级索引列值 + 主键值 - 不存整行
- 二级索引查整行时,先拿主键再去聚簇索引取行,这一步叫回表
- 减少回表通常是优化重点
- 叶子节点存
4. MySQL 常见索引类型
PRIMARY KEY(主键索引)UNIQUE(唯一索引)INDEX(普通索引)- 复合索引(联合索引)
5. 常见索引声明样例
sql
-- 0) 示例表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20),
age INT,
status TINYINT,
created_at DATETIME,
first_name VARCHAR(50),
last_name VARCHAR(50)
);
-- 1) 主键索引(PRIMARY KEY)
-- 方式A:建表时声明(上面 id 已声明)
-- 方式B:后加主键
ALTER TABLE users ADD PRIMARY KEY (id);
-- 2) 唯一索引(UNIQUE)
-- 单列唯一
CREATE UNIQUE INDEX uk_users_email ON users(email);
-- 联合唯一(例如姓名组合唯一)
CREATE UNIQUE INDEX uk_users_name ON users(first_name, last_name);
-- 3) 普通索引(INDEX)
-- 单列普通索引
CREATE INDEX idx_users_age ON users(age);
-- 4) 联合索引 / 复合索引
-- 常见查询:where status=? and created_at>=? order by created_at desc
CREATE INDEX idx_users_status_created ON users(status, created_at);
-- 5) 删除索引
DROP INDEX idx_users_age ON users;
-- 6) 查看索引
SHOW INDEX FROM users;
6. 小结
本文只讲索引,总结为一下段落:
- 为什么需要索引
- 索引优缺点
- InnoDB 的 B+Tree 与存储结构
- 聚簇索引与二级索引
- 常见索引类型与建索引 SQL 样例