当前位置: 首页 > news >正文

从零起步学习MySQL || 第七章:初识索引底层运用及性能优化(结合底层数据结构讲解)

一、什么是 MySQL 中的索引?

定义:
索引是数据库中一种用于 加快数据查询速度 的数据结构。
它就像一本书的“目录”一样,可以让数据库更快地找到你想要的数据,而不需要从头到尾扫描整张表。

简单比喻:
假设有一本 1000 页的书:

  • 没有索引时:你找“第 732 页的某个内容”,只能一页页翻;

  • 有索引时:你看目录就能直接跳转到对应页码。

在 MySQL 中,索引是存储引擎层(如 InnoDB)维护的一种 数据结构,常用的数据结构是 B+ 树


二、为什么需要索引?

索引的主要作用:

  1. 加快数据查询速度

  2. 加快排序、分组等操作

  3. 加快表的连接(JOIN)

  4. 通过唯一索引保证数据唯一性

但要注意:

  • 索引会占用额外的磁盘空间

  • 写入/更新/删除数据时也会维护索引,稍微降低写入性能。

所以:索引是“以空间换时间”的机制。


三、MySQL索引的分类

索引可以按多种维度分类:
我们主要从以下四种维度讲解:

1️⃣ 按 数据结构 分类
2️⃣ 按 物理存储 分类
3️⃣ 按 字段特性 分类
4️⃣ 按 字段个数 分类


① 按数据结构分类

类型底层结构特点举例
B+树索引(最常用)B+ Tree有序、支持范围查询普通索引、主键索引、唯一索引
Hash索引哈希表查找速度快,但不支持范围查询MEMORY 引擎中可用
R-Tree索引空间索引结构用于地理空间数据(GIS)在 MyISAM 中支持
Full-text全文索引倒排索引用于全文搜索在 MyISAM、InnoDB 中都可用

举例:

-- 创建B+树索引(默认)
CREATE INDEX idx_name ON user(name);-- 创建全文索引
CREATE FULLTEXT INDEX idx_content ON article(content);


② 按物理存储分类

类型是否和数据一起存储特点举例
聚簇索引(Clustered Index)数据与索引存储在一起主键索引,每个表只能有一个InnoDB 主键
非聚簇索引(Non-Clustered Index)索引与数据分开存储存储的是数据地址或主键值普通索引、唯一索引

举例:

-- InnoDB 聚簇索引
CREATE TABLE student (id INT PRIMARY KEY,       -- 主键聚簇索引name VARCHAR(50),age INT,INDEX idx_name(name)      -- 非聚簇索引
);

解释:

  • id 是主键 → 聚簇索引;

  • idx_name 是普通索引 → 非聚簇索引。


③ 按字段特性分类

类型特点举例
主键索引(Primary Key)唯一且不能为 NULL,每个表只能有一个PRIMARY KEY(id)
唯一索引(Unique Index)值唯一但可为 NULLUNIQUE INDEX idx_email(email)
普通索引(Normal Index)无限制INDEX idx_name(name)
全文索引(Full-text Index)用于文本匹配FULLTEXT(content)

举例:

CREATE TABLE user (id INT PRIMARY KEY,                -- 主键索引email VARCHAR(100) UNIQUE,         -- 唯一索引name VARCHAR(50), INDEX idx_name(name),              -- 普通索引FULLTEXT INDEX idx_bio(bio)        -- 全文索引
);


④ 按字段个数分类

类型特点举例
单列索引只对一个字段建立索引INDEX idx_name(name)
联合索引(复合索引)对多个字段联合建立索引INDEX idx_user(name, age)

举例:

-- 单列索引
CREATE INDEX idx_name ON user(name);-- 联合索引
CREATE INDEX idx_name_age ON user(name, age);

注意:
联合索引遵循 最左前缀原则,即索引 (name, age) 实际上相当于对:

  • (name)

  • (name, age)
    有索引效果,但对 (age) 单独无效。


四、总结表格一览

分类维度类型示例
按数据结构B+树索引、Hash索引、R-Tree、全文索引CREATE INDEX idx_name ON user(name)
按物理存储聚簇索引、非聚簇索引主键索引 vs 普通索引
按字段特性主键、唯一、普通、全文PRIMARY KEY(id)UNIQUE(email)
按字段个数单列索引、联合索引(name)(name, age)

补充讲解:

补充一 、最左匹配原则(Leftmost Prefix Rule)

✅ 1. 定义

“最左匹配原则”是指:

联合索引会从最左边的字段开始匹配,只有按照最左的字段顺序使用索引,索引才会生效。

换句话说:
MySQL 从联合索引的 第一个字段 开始匹配条件,
当中途遇到 范围查询(如 >, <, BETWEEN, LIKE 'xxx%' 时,就会停止继续匹配后面的字段。


✅ 2. 举例讲解

假设我们有如下表:

CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(50),age INT,sex CHAR(1),INDEX idx_name_age_sex(name, age, sex)
);

索引的顺序是:(name, age, sex)


📘 例1:完整匹配(使用索引)

SELECT * FROM user WHERE name = 'Tom' AND age = 20 AND sex = 'M';

✅ 按 (name, age, sex) 顺序依次匹配,用到了全部三列索引
👉 索引使用情况:name → age → sex


📘 例2:部分匹配(仍然使用索引)

SELECT * FROM user WHERE name = 'Tom' AND age = 20;

✅ 用到了前两列 (name, age)
👉 索引使用情况:name → age


📘 例3:只用最左字段(仍使用索引)

SELECT * FROM user WHERE name = 'Tom';

✅ 用到了索引的第一列 name
👉 索引使用情况:name


📘 例4:跳过最左字段(索引失效)

SELECT * FROM user WHERE age = 20;

❌ 不符合最左匹配原则,因为没有使用 name
👉 索引 完全失效,需要全表扫描。


📘 例5:范围查询中断匹配

SELECT * FROM user WHERE name = 'Tom' AND age > 18 AND sex = 'M';

✅ 只会使用 (name, age) 索引部分;
❌ 不会使用 sex,因为 age > 18 是范围查询。
👉 索引使用情况:name → age(停止)


📘 例6:顺序不一致但可优化

SELECT * FROM user WHERE age = 20 AND name = 'Tom';

✅ 虽然条件顺序不一致,但 MySQL 优化器会自动调整 顺序,依然可以使用 (name, age) 索引。


📘 例7:LIKE 前缀匹配可用索引

SELECT * FROM user WHERE name LIKE 'T%';

LIKE 'T%' 等价于范围查询 'T' <= name < 'U',仍然可用索引。

但:

SELECT * FROM user WHERE name LIKE '%Tom%';

❌ 前面有通配符 %,索引失效。


三、索引下推(Index Condition Pushdown, ICP)

✅ 1. 定义

索引下推(ICP) 是 MySQL 5.6 引入的一种 索引优化机制

在没有 ICP 之前,MySQL 在通过索引定位到数据行后,会把这些行提取出来交给 Server 层 再做 WHERE 条件判断。
而有了 ICP 后,一部分 WHERE 条件判断可以 在存储引擎层完成,减少回表次数,提高性能。


✅ 2. 举例说明

仍然以这个表为例:

CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(50),age INT,sex CHAR(1),INDEX idx_name_age(name, age)
);


📘 示例1:没有索引下推的情况
SELECT * FROM user WHERE name LIKE 'Tom%' AND age = 20;

假设联合索引 (name, age)

  • name LIKE 'Tom%' 是范围查询;

  • 所以索引只能匹配 name,不能直接匹配 age

🔹 没有 ICP 时的执行逻辑:

  1. 通过索引扫描所有 name'Tom%' 开头的记录;

  2. 每匹配一条记录,都回表取完整行;

  3. 再在 Server 层 判断 age = 20

  4. 不符合的行被丢弃。

👉 缺点:回表次数太多(磁盘 IO 多)。


📘 示例2:启用索引下推的情况(ICP)

有 ICP 时:

  1. 通过索引扫描 name LIKE 'Tom%'

  2. 在索引层直接判断 age = 20

  3. 只有满足 age = 20 的行才回表取数据。

👉 优势:

  • 减少回表次数;

  • 大幅提升查询效率。


✅ 3. ICP 的触发条件

  • 必须是 InnoDB 或 MyISAM 引擎;

  • 必须是 联合索引

  • 查询语句中有 范围查询 + 其他条件

  • 其他条件可以在索引中判断的情况下才生效。

    最左匹配 + 索引下推 对比总结

    特性最左匹配原则索引下推(ICP)
    定义联合索引从最左字段开始依次匹配,中断后不再匹配在存储引擎层提前过滤数据,减少回表
    作用阶段索引匹配阶段存储引擎读取阶段
    是否减少IO 是
    是否加速查询 是 是
    触发条件联合索引范围查询 + 其他索引列条件
    执行计划标识key=idx_xxxUsing index condition
http://www.dtcms.com/a/516523.html

相关文章:

  • CVPR2025 | OPS | 通过假设空间增强提升对抗迁移性
  • 自己做的网站怎么才能在百度上查找郑州定制网站推广工具产品
  • 如何从小白变成rust糕手
  • 注册一个网站多少钱?哪个网站可以免费建站
  • GCC与Makefile常用基础知识
  • 类装饰器
  • 什么网站可以直接做word如何在外管局网站做付汇延期
  • Dify从入门到精通 第22天 利用分支与判断构建智能路由客服机器人
  • 网站底备案号链接代码商丘建设厅网站首页
  • 【C++】手搓AVL树
  • 【完整源码+数据集+部署教程】【天线&其他】月球表面状况检测系统源码&数据集全套:改进yolo11-unireplknet
  • Flutter---弹窗
  • 从零开始学习RabbitMQ
  • 台州市住房和城乡建设局网站做美容美发学校网站公司
  • [答疑]考虑复用,尺度应该怎样把握
  • 注册网站借钱平台犯不犯法个人网站logo需要备案吗
  • 最新电大网站开发维护竞价托管推广代运营
  • 字符串统计
  • Docker与Tomcat:一键部署Java Web应用的完美组合
  • 【同步/异步 日志系统】 --- 前置技术
  • 图论基础和表示
  • 网站建设为了什么怎么看网站谁做的
  • [小白]spring boot接入emqx
  • Spring Boot 实现GZIP压缩优化
  • Spring Boot使用Redis实现消息队列
  • 互联网大厂Java面试实战:以Spring Boot与微服务为核心的技术场景剖析
  • 做网站页面的软件毕业设计网站成品
  • 《一个浏览器多人用?Docker+Neko+cpolar实现跨网共享》
  • design设计网站网站优化方法页面
  • C++基础:(十七)模版进阶:深入探索非类型参数、特化、分离编译与实战技巧