MySQL 索引介绍

作者:

在

这份笔记一共 5 种索引:B 树、B + 树、HASH 索引、FULLTEXT 全文索引、R 树 (RTREE) 空间索引,重点是 B + 树(InnoDB 默认)。

1. B 树(多路平衡查找树)

B + 树是 B 树的改良版本,先看懂 B 树更好理解。

结构特点

  1. 每个节点可以存多个关键字 + 指针
  2. 所有叶子节点在同一层,树高度平衡,查询稳定
  3. 关键字有序,子树关键字范围和父节点对应

B 树:非叶子节点、叶子节点都保存数据

适用场景

精确查询、范围查询。

实际 MySQL 很少直接用原生 B 树,用的是它的变种:B + 树


2. B + 树(⭐最重要,InnoDB 默认索引)

B + 树是 B 树优化版本,InnoDB 引擎默认索引,面试最高频。

结构特点

  1. 非叶子节点只存关键字 + 指针,不存真实数据;只有叶子节点存放完整数据
  2. 所有叶子节点用双向链表按顺序串起来,方便范围查找
  3. 全部叶子节点在同一层,查询时间稳定 O (log n)

✅ 优势

  • 精确查询 + 范围查询都很强(BETWEEN、>、<、ORDER BY排序)
  • 磁盘 IO 少:单个节点可以存放更多索引关键字,减少读磁盘次数
  • 适合大数据量,性能稳定

适用场景: 主键索引、单列索引、联合索引(遵守最左前缀原则)、频繁范围查询 / 排序。

InnoDB 主键索引是聚簇索引:叶子节点直接存放整行数据;普通二级索引叶子节点存放主键值。

3. HASH 索引(哈希索引)

基于哈希表实现

结构特点

对索引字段计算哈希值,哈希值直接映射数据地址。理想情况查找复杂度 O (1)

✅优点:等值精确匹配极快 where id=100 速度优于 B + 树 ❌缺点(高频考点)

  1. 不支持范围查询、不支持排序:哈希值是乱序,不能用> < BETWEEN ORDER BY
  2. 哈希冲突:不同关键字算出相同哈希,需要链表处理,性能下降
  3. 联合索引只能完整匹配全部字段,不能走前缀匹配

适用场景:只做等值查询

MySQL:Memory 引擎支持手动创建 HASH 索引;InnoDB 自适应哈希索引是内部自动维护,不能手动创建

4. FULLTEXT 全文索引

用于大文本关键词检索(文章、评论),底层是倒排索引 原理:把文本拆分成单词 (Term),记录哪个单词出现在哪些文档里。

✅优点: 文本关键词检索,远快于 LIKE '%关键词%'(%前缀通配无法走普通索引,全表扫描) 使用语法:MATCH(字段) AGAINST('关键词')

❌限制

  1. 只支持文本类型:CHAR/VARCHAR/TEXT
  2. 有最小词长限制,不同引擎支持不一样
  3. 不能做部分词语匹配:搜 “数据” 不能命中 “数据库”

场景:博客、文章内容搜索

-- 创建全文索引
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 索引创建与删除语法

三种建索引方式

  1. 建表的时候直接定义索引
CREATE TABLE 表名 (
字段1 数据类型,
字段2 数据类型,
[UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名(字段名)
);
  1. 表已经存在,用 CREATE 创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名
ON 表名 (字段名);
  1. 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;
#查看去重数据行数

一、基础概念

  1. 索引建立在表的列(字段)上 索引不是整张表的,是给某一个 / 多个字段单独建立的结构。
  2. 在 where 后面的列建立索引,才会加快查询速度

举例:select * from test where name='张三' where 条件用了name,给name建索引,这条查询才能提速; 如果 where 用 age,索引建在 name 上,这条 SQL不会走索引。

  1. pages <---索引(属性)<---查数据 简单理解流程: SQL 查询 → 先去索引页快速定位记录位置 → 再根据索引找到真实数据页读取数据

==索引相当于书本的目录,目录(索引)只记录页码,真正内容在正文(数据表)==。

二、索引分类

(这里是从约束功能划分,不是底层 B+/HASH)

注意区分:前面讲的 B+、HASH 是底层数据结构;这里主键 / 普通 / 唯一索引,是逻辑类型,InnoDB 底层默认都是 B + 树

  1. 主键索引(PRIMARY KEY)
    • 主键字段的值不能重复、不能为 NULL
    • 一张表只能有 1 个主键索引,InnoDB 主键是聚簇索引,叶子节点存整行数据
  2. *普通索引(INDEX)【笔记带 ,重点】**
    • 最基础索引,只用来加速查询,不限制字段是否重复、是否为空
    • 字段可以重复,可以 NULL;单纯提升 where 查询速度
  3. 唯一索引(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;

image-20261017201122273

image-20261017201346449

3. 删除索引

alter table test drop index index_name;

test 是表名,index_name 是要删除的索引名称

image-20261017201720016

4. 添加【唯一索引】

alter table test add unique key uni_xxx(xxx);

test:表名;uni_xxx:唯一索引名字;括号 xxx:字段名

==添加主键索引:alter table 表名 add primary key(字段);==

image-20261017202340570

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 位,不是完整字符串。

✅ 一句话:前缀索引的本质是索引存储的数据变短,和索引命名无关

image-20261017210103572


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) 能走索引的查询:

  1. where gender='m'
  2. where gender='m' and age=20
  3. where gender='m' and age=20 and money=1000

❌ 不能正常走这个联合索引: where age=20 或者 where money=1000

==跳过了最左边的gender,索引失效==。

==幻灯片原话:把最常用来作为条件查询的列放在最前面== ==设计联合索引,查询频率越高、区分度越高的字段,越靠左。==

通俗理解

联合索引相当于给书本建目录:先按 gender 分类,同 gender 内部再按 age 排序,age 相同再按 money 排序。 查找必须从目录第一层开始;跳过第一层直接找 age,就没法用这个目录。

image-20261017210932789


四、附带两条 count 统计 SQL

select count(*) from city;
-- 统计表一共有多少行数据(包含null行)
select count(distinct(name)) from city;
-- distinct 去重:统计name字段有多少种不重复的值

例子:name 列:张三、李四、张三 count(distinct name) 结果 = 2(张三、李四)

易错点小结

  1. 索引不是越多越好:索引会加快查询,但是减慢新增 / 修改 / 删除(增删改需要同步维护索引)
  2. ==索引建在 where 字段才生效;select 后面的字段建索引,一般不会提速==
  3. 分类区分:
    • 按底层结构:B + 树、HASH、全文索引
    • 按逻辑功能:主键索引、普通索引、唯一索引

MySQL 索引考点

  1. 前缀索引 只支持字符串类型(varchar),数值类型不能建立前缀索引;语法字段(N),只截取字段前 N 个字符建立索引,show index中通过Sub_part列能看到截取长度。
  2. 联合索引(复合索引) 本质1 个索引,里面包含多个字段,≠ 分别给每个字段单独建 3 个独立单字段索引;字段顺序很关键。
  3. 最左前缀原则(高频考点) 联合索引生效规则:查询条件要从索引最左边开始连续匹配字段,跳过左边字段,索引后面部分就无法使用。

一句话区分: 前缀索引:同一个字符串字段,只取前面一部分字符; 联合索引:多个不同字段打包成一个索引,遵守最左前缀。