这份笔记一共 5 种索引:B 树、B + 树、HASH 索引、FULLTEXT 全文索引、R 树 (RTREE) 空间索引,重点是 B + 树(InnoDB 默认)。
1. B 树(多路平衡查找树)
B + 树是 B 树的改良版本,先看懂 B 树更好理解。
结构特点
- 每个节点可以存多个关键字 + 指针
- 所有叶子节点在同一层,树高度平衡,查询稳定
- 关键字有序,子树关键字范围和父节点对应
B 树:非叶子节点、叶子节点都保存数据
适用场景
精确查询、范围查询。
实际 MySQL 很少直接用原生 B 树,用的是它的变种:B + 树
2. B + 树(⭐最重要,InnoDB 默认索引)
B + 树是 B 树优化版本,InnoDB 引擎默认索引,面试最高频。
结构特点
- 非叶子节点只存关键字 + 指针,不存真实数据;只有叶子节点存放完整数据
- 所有叶子节点用双向链表按顺序串起来,方便范围查找
- 全部叶子节点在同一层,查询时间稳定 O (log n)
✅ 优势
- 精确查询 + 范围查询都很强(
BETWEEN、>、<、ORDER BY排序) - 磁盘 IO 少:单个节点可以存放更多索引关键字,减少读磁盘次数
- 适合大数据量,性能稳定
适用场景: 主键索引、单列索引、联合索引(遵守最左前缀原则)、频繁范围查询 / 排序。
InnoDB 主键索引是聚簇索引:叶子节点直接存放整行数据;普通二级索引叶子节点存放主键值。
3. HASH 索引(哈希索引)
基于哈希表实现
结构特点
对索引字段计算哈希值,哈希值直接映射数据地址。理想情况查找复杂度 O (1)
✅优点:等值精确匹配极快 where id=100 速度优于 B + 树
❌缺点(高频考点)
- 不支持范围查询、不支持排序:哈希值是乱序,不能用
> < BETWEEN ORDER BY - 哈希冲突:不同关键字算出相同哈希,需要链表处理,性能下降
- 联合索引只能完整匹配全部字段,不能走前缀匹配
适用场景:只做等值查询
MySQL:Memory 引擎支持手动创建 HASH 索引;InnoDB 自适应哈希索引是内部自动维护,不能手动创建
4. FULLTEXT 全文索引
用于大文本关键词检索(文章、评论),底层是倒排索引 原理:把文本拆分成单词 (Term),记录哪个单词出现在哪些文档里。
✅优点:
文本关键词检索,远快于 LIKE '%关键词%'(%前缀通配无法走普通索引,全表扫描)
使用语法:MATCH(字段) AGAINST('关键词')
❌限制
- 只支持文本类型:
CHAR/VARCHAR/TEXT - 有最小词长限制,不同引擎支持不一样
- 不能做部分词语匹配:搜 “数据” 不能命中 “数据库”
场景:博客、文章内容搜索
-- 创建全文索引
CREATE FULLTEXT INDEX idx_article_content ON article(content);
-- 查询示例
SELECT * FROM article
WHERE MATCH(content) AGAINST('数据库 索引' IN BOOLEAN MODE);
5. RTREE(R 树 空间索引 SPATIAL INDEX)
专门用于地理空间数据(坐标、几何图形)
- 多维空间索引,处理点、线、面
- 可以做空间范围查询:查找某坐标附近的点
适用场景:GIS 地理信息、经纬度,例如:查找距离某个坐标 1 公里内的店铺
CREATE TABLE places (
id INT,
location POINT, -- 空间点类型
SPATIAL INDEX idx_location(location) -- R树空间索引
)ENGINE=InnoDB;
查询函数:ST_Distance_Sphere 计算球面距离
MySQL 索引创建与删除语法
三种建索引方式
- 建表的时候直接定义索引
CREATE TABLE 表名 (
字段1 数据类型,
字段2 数据类型,
[UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名(字段名)
);
- 表已经存在,用 CREATE 创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名
ON 表名 (字段名);
- ALTER TABLE 添加索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名(字段名);
删除索引
DROP INDEX 索引名 ON 表名;
索引类型快速对比总结(方便背诵)
表格
| 索引 | 底层 | 擅长 | 短板 |
|---|---|---|---|
| B + 树 | 多路平衡树 | 等值、范围、排序、联合索引 | 单纯等值查询略慢于 hash |
| HASH | 哈希表 | 等值精确查询 | 不支持范围、排序、前缀匹配、哈希冲突 |
| FULLTEXT | 倒排索引 | 大文本关键词搜索 | 不能模糊部分匹配,仅限文本 |
| RTREE | R 树 | 地理坐标空间范围查询 | 普通业务几乎不用 |
面试重点一句话
InnoDB 默认索引是 B + 树; B + 树叶子节点链表,适合范围查询; HASH 索引只能等值查询,不能范围和排序; 全文索引用来替代
like '%xxx%'文本检索。
总结:
多路平衡树(B 树 / B + 树)就是 “综合型选手”,兼顾等值查找 + 范围查找 + 排序,通用性最强;而 Hash 索引是专精型选手,只擅长等值查询。
多路平衡树(B + 树)设计目标:不要只专精单一查询,而是绝大多数 SQL 场景都能用,性能稳定。 Hash:单点查询极限速度快,但适用场景窄。
考试背诵版: ==B + 树属于多路平衡查找树,多路可以降低树高减少磁盘 IO;平衡保证查询性能稳定。支持等值查询、范围查询、排序,综合能力强,是 InnoDB 默认索引==。
Mysql的索引管理
这一页是MySQL 索引的基础分类 + 增删查索引 SQL 命令,偏实操
添加索引:
alter table test add index index_name(name);
#创建索引
create index index_name on test(name);
#创建索引
desc table;
#查看索引
show index from table;
#查看索引
alter table test drop key index_name;
#删除索引
alter table student add unique key uni_xxx(xxx);
#添加主键索引(略)
#添加唯一性索引
select count(*) from city;
#查看表中数据行数
select count(distinct(name)) from city;
#查看去重数据行数
一、基础概念
- 索引建立在表的列(字段)上 索引不是整张表的,是给某一个 / 多个字段单独建立的结构。
- 在 where 后面的列建立索引,才会加快查询速度
举例:
select * from test where name='张三'where 条件用了name,给name建索引,这条查询才能提速; 如果 where 用 age,索引建在 name 上,这条 SQL不会走索引。
pages <---索引(属性)<---查数据简单理解流程: SQL 查询 → 先去索引页快速定位记录位置 → 再根据索引找到真实数据页读取数据
==索引相当于书本的目录,目录(索引)只记录页码,真正内容在正文(数据表)==。
二、索引分类
(这里是从约束功能划分,不是底层 B+/HASH)
注意区分:前面讲的 B+、HASH 是底层数据结构;这里主键 / 普通 / 唯一索引,是逻辑类型,InnoDB 底层默认都是 B + 树
- 主键索引(PRIMARY KEY)
- 主键字段的值不能重复、不能为 NULL
- 一张表只能有 1 个主键索引,InnoDB 主键是聚簇索引,叶子节点存整行数据
- *普通索引(INDEX)【笔记带 ,重点】**
- 最基础索引,只用来加速查询,不限制字段是否重复、是否为空
- 字段可以重复,可以 NULL;单纯提升 where 查询速度
- 唯一索引(UNIQUE KEY)
- 索引字段不能重复,但是允许为 NULL(可以多个 null)
- 两个作用:①加快查询;②自动约束,防止插入重复数据
对比记忆: 主键:不可重复 + 不可 NULL,一张表只能 1 个 唯一索引:不可重复,允许 NULL,一张表可以多个 普通索引:无重复限制,只提速
三、索引 SQL 命令(重点,上机默写)
1. 添加【普通索引】两种写法
写法 1:alter table 添加索引
alter table test add index index_name(name);
- test:表名
- index_name:你自己起的索引名
- name:建立索引的字段
写法 2:create index
create index index_name on test(name);
效果和上面完全一样,两种都可以。
2. 查看索引
desc table;
-- 简写查看表结构,能看到索引
show index from table;
-- 完整查看这张表所有索引详细信息(考试更推荐这个)
把 table 替换成真实表名,如
show index from test;


3. 删除索引
alter table test drop index index_name;
test 是表名,index_name 是要删除的索引名称

4. 添加【唯一索引】
alter table test add unique key uni_xxx(xxx);
test:表名;uni_xxx:唯一索引名字;括号 xxx:字段名
==添加主键索引:
alter table 表名 add primary key(字段);==

5、前缀索引
==根据字符串字段的前 N 个字符建立索引==
alter table test add index idx_name(name(10));
- 含义:对
name字段,只取前 10 个字符来构建索引,而不是把完整 name 全部放进索引。 - 适用场景:
varchar、text这类长文本字段。 - 优点:索引体积更小、占用磁盘少,查询更快;
- 原理举例:城市名称 Dallas、Denver,只拿开头字母 / 前几个字符做索引,就能快速过滤数据。
- 一句话:不要直接给很长的字符串整列建索引,优先前缀索引
⚠️ 缺点:
只能匹配前缀,where name like '%xxx'(前缀模糊查询)用不上前缀索引;
截取字符数量要选合适,太短区分度差,太长节约空间效果不明显。
深入理解:
name(10) 这里的(10)不是索引名字,是定义索引:只把 name 字段前 10 个字符存入索引树。
- 索引名叫
idx_name可以随便改(比如 aaaaaaa),不影响前缀索引功能; - ==真正决定它是前缀索引的,是字段后面括号里的长度
(10);== - 存储:索引 B + 树里面只保存字符串开头 N 位,不是完整字符串。
✅ 一句话:前缀索引的本质是索引存储的数据变短,和索引命名无关

6、联合索引(复合索引)
多个字段,合并成一个索引,不是多个独立索引
-- 建表
create table people (id int,name varchar(20),age tinyint,money int ,gender enum('m','f'));
-- 创建联合索引:idx_gam,包含 gender,age,money 三个字段
alter table people add index idx_gam(gender,age,money);
✅ 最核心原则:最左前缀原则
索引顺序 (gender,age,money)
能走索引的查询:
where gender='m'where gender='m' and age=20where gender='m' and age=20 and money=1000
❌ 不能正常走这个联合索引:
where age=20 或者 where money=1000
==跳过了最左边的
gender,索引失效==。
==幻灯片原话:把最常用来作为条件查询的列放在最前面== ==设计联合索引,查询频率越高、区分度越高的字段,越靠左。==
通俗理解
联合索引相当于给书本建目录:先按 gender 分类,同 gender 内部再按 age 排序,age 相同再按 money 排序。 查找必须从目录第一层开始;跳过第一层直接找 age,就没法用这个目录。

四、附带两条 count 统计 SQL
select count(*) from city;
-- 统计表一共有多少行数据(包含null行)
select count(distinct(name)) from city;
-- distinct 去重:统计name字段有多少种不重复的值
例子:name 列:张三、李四、张三
count(distinct name) 结果 = 2(张三、李四)
易错点小结
- 索引不是越多越好:索引会加快查询,但是减慢新增 / 修改 / 删除(增删改需要同步维护索引)
- ==索引建在 where 字段才生效;select 后面的字段建索引,一般不会提速==
- 分类区分:
- 按底层结构:B + 树、HASH、全文索引
- 按逻辑功能:主键索引、普通索引、唯一索引
MySQL 索引考点
- 前缀索引
只支持字符串类型(
varchar),数值类型不能建立前缀索引;语法字段(N),只截取字段前 N 个字符建立索引,show index中通过Sub_part列能看到截取长度。 - 联合索引(复合索引) 本质1 个索引,里面包含多个字段,≠ 分别给每个字段单独建 3 个独立单字段索引;字段顺序很关键。
- 最左前缀原则(高频考点) 联合索引生效规则:查询条件要从索引最左边开始连续匹配字段,跳过左边字段,索引后面部分就无法使用。
一句话区分: 前缀索引:同一个字符串字段,只取前面一部分字符; 联合索引:多个不同字段打包成一个索引,遵守最左前缀。