MySQL 索引基础笔记(小白友好版)
一句话理解:索引就是书的目录。 没有目录,找内容得一页页翻(全表扫描);有了目录,直接翻到对应页(使用索引),速度飞快。
一、 什么是索引(Index)
官方定义 :一种帮助 MySQL 提高查询效率的数据结构。索引本身也就是一种数据结构。
1. 索引的优点
- 大大加快数据的查询速度(最核心的作用)。
2. 索引的缺点
- 耗资源:维护索引需要耗费数据库的 CPU 和内存资源。
- 占空间:索引需要占用额外的磁盘空间。
- 拖慢增删改 :当对表的数据进行
INSERT、UPDATE、DELETE时,数据库不仅要改数据,还要去维护索引树,速度会受到影响。
💡 总结:索引是用"空间"和"增删改的性能",来换取"查询的速度"。
二、 索引分类
1. 按功能/物理结构分类(InnoDB 引擎)
-
a. 主键索引 (Primary Key)
- 设定主键后,数据库会自动建立主键索引。
- 特点 :在 InnoDB 引擎中,主键索引是聚簇索引。
- 规则 :主键索引的列不能为空。
-
b. 普通索引 (Normal Index)
- 即一个索引只包含单个列,一个表可以有多个普通索引。
- 特点:没有任何唯一性限制,纯粹为了加速查询。
-
c. 唯一索引 (Unique Index)
- 索引列的值必须唯一,但允许为空(只能有一个为空)。
-
d. 复合索引 (Composite Index)
- 即一个索引包含多个列。
- 原则 :使用时严格遵循最左前缀原则(下面会细说)。
2. 全文索引 (Full Text) - 补充说明
- 作用:在文本中查找关键词(类似搜索引擎的模糊搜索),允许插入重复值和空值。
- 适用列 :可以在
CHAR、VARCHAR、TEXT类型列上创建。 - ⚠️ 误区 :在mysql5.6 之前"只有 MYISAM 引擎支持全文索引"。在 MySQL 5.6 及以上版本,InnoDB 也支持全文索引了。
三、 索引的基本操作
0. 查看与删除索引
sql
-- 查看表上的索引
SHOW INDEX FROM 表名;
-- 删除索引
DROP INDEX 索引名 ON 表名;
1. 主键索引(自动创建)
sql
-- 创建表时指定主键,自动生成主键索引
CREATE TABLE t_user(
id VARCHAR(20) PRIMARY KEY,
name VARCHAR(20)
);
2. 普通索引
sql
-- 建表时创建(推荐用 KEY,效果同 INDEX)
CREATE TABLE t_user(
id VARCHAR(20) PRIMARY KEY,
name VARCHAR(20),
KEY(name)
);
-- 建表后追加创建
CREATE INDEX nameindex ON t_user(name);
3. 唯一索引
sql
-- 建表时创建
CREATE TABLE t_user(
id VARCHAR(20) PRIMARY KEY,
name VARCHAR(20),
UNIQUE(name)
);
-- 建表后追加创建
CREATE UNIQUE INDEX name_unique_index ON t_user(name);
4. 复合索引(多列索引)
sql
-- 建表时创建
CREATE TABLE t_user3(
id VARCHAR(20) PRIMARY KEY,
name VARCHAR(20),
age VARCHAR(20),
KEY(name, age)
);
-- 建表后追加创建
CREATE INDEX name_age_bir_index ON t_user(name, age, bir);
四、 MySQL 索引底层原理(B+Tree)
MySQL(InnoDB)的索引底层数据结构是 B+Tree。
1. B+Tree 的特点
- 只有叶子节点存放真实数据(或者主键值),非叶子节点只存索引键和指针。
- 树的层级很少(通常 2~4 层),能极大地减少磁盘 I/O 次数。
- 叶子节点之间用双向链表连接,非常适合范围查询(如
BETWEEN、>、<)。
2. B-Tree 和 B+Tree 的区别
- B-Tree 的非叶子节点也会存数据,导致树会更高、更胖,查询效率不稳定。
- B+Tree 数据都在叶子节点,每次查询找数据的次数(I/O 次数)是固定的,性能更稳定。
💡 补充 :每页默认存储 16KB。MySQL 在磁盘和内存之间交互数据的最小单位是"页(Page)",InnoDB 默认一页是 16KB。
五、 聚簇索引和非聚簇索引
1. 聚簇索引(Clustered Index)
- 大白话:索引和数据"绑"在一起,找到了索引,就找到了整行数据。
- 核心 :InnoDB 的主键索引就是聚簇索引。叶子节点里装的就是这一行所有的数据。
2. 非聚簇索引(二级索引 / 辅助索引)
- 大白话:索引和数据"分家"了。
- 范围:普通索引、唯一索引、复合索引都是非聚簇索引。
- 结构 :它们的叶子节点里存的不是整行数据,而是主键的值。
⚠️ 什么是"回表"?
如果我要查
SELECT * FROM t_user WHERE name='张三'(假设name是普通索引):
- MySQL 会先在
name的索引树里找到"张三"对应的主键 id。- 然后再拿这个 id 去主键索引树 里查整行数据。
这个"拿着主键再去查一次"的过程就叫回表。
六、 执行计划(EXPLAIN)
当你不知道 SQL 语句跑得快不快、有没有走索引时,在 SQL 前面加上 EXPLAIN 就可以查看执行计划。
sql
EXPLAIN SELECT * FROM t_user WHERE name = '张三';
小白最需要关注的几个参数:
-
type(非常关键)- 表示查询的访问类型。好到坏的顺序大致是:
system>const>eq_ref>ref>range>index>ALL。 - 如果看到
ALL,说明是全表扫描,没走索引,数据量大时极慢,必须优化。
- 表示查询的访问类型。好到坏的顺序大致是:
-
key- 实际使用的索引名称。如果为
NULL,说明没有使用索引。
- 实际使用的索引名称。如果为
-
rows- MySQL 预估要扫描多少行数据才能找到结果。越少越好。
-
Extra(额外信息)- 如果看到
Using index:说明用了"覆盖索引",性能极好(不需要回表)。 - 如果看到
Using filesort:说明在内存或磁盘里做了额外排序,可能需要优化。 - 如果看到
Using temporary:说明使用了临时表,性能较差。
- 如果看到