MySQL索引原理、分类与优化实战深入理解

 更新时间:2026年06月04日 10:54:51   作者:一条泥憨鱼  
索引是一种特殊的数据结构,用于加快数据库表中数据的检索速度,它类似于书籍的目录,通过建立一个指向数据行的快速查找路径,这篇文章主要介绍了MySQL索引原理、分类与优化实战的相关资料,需要的朋友可以参考下

前言:

在学习 MySQL 的过程中,“索引(Index)”一定是最核心、最重要的知识之一。

很多初学者第一次接触索引时,会觉得:

  • 概念抽象

  • 原理复杂

  • B+树难懂

  • 优化不会写

但实际上:

索引的本质,就是帮助数据库“快速查找数据”。

你可以把它理解成:

书籍的目录

如果一本书没有目录,你想找某一页内容,就只能

一页一页翻

但如果有目录,你就能快速定位

MySQL 索引也是同样的道理。

这篇文章将从:

  • 什么是索引

  • 为什么需要索引

  • 索引底层原理

  • B+树结构

  • 索引分类

  • 索引失效

  • SQL优化

等多个角度,带你彻底理解 MySQL 索引。

一、什么是索引?

索引(Index)是数据库中一种:

用于提高查询效率的数据结构。

它的作用:

加快数据查询速度

例如:

我们有一张用户表:

CREATE TABLE user(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20),
    age INT
);

插入10万条数据后:

如果执行:

SELECT * FROM user WHERE name='张三';

MySQL 会:

从第一条开始
一条一条找

这种方式叫:

全表扫描

效率非常低。

如果给 name 字段添加索引

CREATE INDEX idx_name ON user(name);

数据库就能快速定位数据,查询速度会大幅提升。

二、为什么索引能提高查询速度?

核心原因:

减少数据扫描次数

没有索引:

100万条数据
可能扫描100万次

有索引:

可能只需要扫描几次

这就像:

没有目录的书

你想找:

第500页内容

只能:

从第一页翻到500页

有目录的书

直接:

目录 → 第500页

效率差距巨大。

三、索引的底层数据结构

很多面试中都会问:

MySQL索引底层是什么?

答案:

B+Tree(B+树)

四、为什么不用数组或链表?

4.1 数组的问题

数组查找快:

支持下标随机访问

但是插入数据很慢。

例如:

1 2 4 5

插入3:

1 2 3 4 5

后面元素都要移动。

数据库频繁增删改,数组不适合。

4.2 链表的问题

链表插入快,但查询慢。

因为:

只能一个一个找

不适合数据库查询。

4.3 二叉树的问题

普通二叉树:

可能退化成链表。

例如:

1
 \
  2
   \
    3
     \
      4

查询效率很差。

五、B+树是什么?

MySQL 最常用的索引结构:

B+Tree

它是一种:

多路平衡搜索树

特点:

  • 查询快

  • 层级少

  • 磁盘IO少

  • 非常适合数据库

六、B+树结构特点

6.1 所有数据都在叶子节点

B+树中:

真正的数据:

只存储在叶子节点

非叶子节点只存索引。

6.2 叶子节点形成链表

叶子节点之间,会形成双向链表

因此:

范围查询效率极高

例如:

SELECT * FROM user WHERE id BETWEEN 100 AND 200;

6.3 树高度低

B+树的一个节点能存很多数据。

因此:

树层级很少

通常:

3~4层

就能存千万级数据。

七、聚簇索引与非聚簇索引

这是 MySQL 高频面试题。

7.1 聚簇索引(Clustered Index)

InnoDB 中,主键索引就是聚簇索引

特点:

数据和索引放在一起

例如:

PRIMARY KEY(id)

叶子节点,直接存整行数据。

7.2 非聚簇索引(二级索引)

普通索引:

CREATE INDEX idx_name ON user(name);

叶子节点存的是:

主键值

查询时,还要回到主键索引查数据。

这个过程叫:

回表查询

八、索引分类

8.1 主键索引

创建主键时自动生成。

CREATE TABLE student(
    id INT PRIMARY KEY,
    name VARCHAR(20)
);

特点:

  • 唯一

  • 不能为空

8.2 唯一索引

保证字段唯一。

CREATE UNIQUE INDEX idx_phone
ON user(phone);

例如:

手机号不能重复。

8.3 普通索引

最常见。

CREATE INDEX idx_age
ON user(age);

仅用于提高查询效率。

8.4 联合索引(复合索引)

多个字段共同组成。

CREATE INDEX idx_name_age
ON user(name,age);

适用于:

WHERE name=? AND age=?

8.5 全文索引

用于:

文本搜索

例如:

FULLTEXT(content)

九、创建索引

9.1 创建普通索引

CREATE INDEX idx_name
ON user(name);

9.2 创建唯一索引

CREATE UNIQUE INDEX idx_email
ON user(email);

9.3 创建联合索引

CREATE INDEX idx_name_age
ON user(name,age);

9.4 删除索引

DROP INDEX idx_name ON user;

十、查看SQL是否使用索引

使用:

EXPLAIN

例如:

EXPLAIN
SELECT * FROM user WHERE name='张三';

十一、EXPLAIN重要字段

11.1 type

SQL性能指标。

常见:

type性能
all全表扫描(最差)
index扫描索引
range范围查询
ref普通索引查询
const主键查询(最好)

11.2 key

使用了哪个索引。

11.3 rows

扫描行数越少越好。

十二、索引失效场景

很多时候,明明建了索引,但SQL还是很慢。

原因:

索引失效

12.1 对索引列使用函数

错误示例:

SELECT * FROM user
WHERE YEAR(create_time)=2025;

索引失效。

正确:

SELECT * FROM user
WHERE create_time BETWEEN
'2025-01-01'
AND '2025-12-31';

12.2 模糊查询以%开头

错误:

LIKE '%abc'

索引失效。

正确:

LIKE 'abc%'

12.3 字段类型不一致

例如:

name VARCHAR

但:

WHERE name=123

可能导致隐式转换,索引失效。

12.4 使用or

例如:

WHERE age=18 OR salary=5000

可能索引失效。

12.5 联合索引不满足最左前缀

例如:

(name,age,gender)

SQL:

WHERE age=20

无法使用联合索引。

因为:

没有从最左边开始

十三、最左前缀原则

联合索引最重要的规则。

例如:

(name,age,gender)

可以使用:

WHERE name=?
WHERE name=? AND age=?
WHERE name=? AND age=? AND gender=?

不能直接:

WHERE age=?

十四、覆盖索引

什么是覆盖索引?

即:

查询的数据
刚好都在索引中

不需要回表。

例如:

CREATE INDEX idx_name_age
ON user(name,age);

SQL:

SELECT name,age
FROM user
WHERE name='张三';

由于:

name age 都在索引中

因此:

无需回表

性能更高。

十五、索引不是越多越好

很多初学者认为索引越多越快,其实这是不对的。

15.1 索引占空间

索引需要额外存储。

15.2 更新会变慢

执行:

INSERT
UPDATE
DELETE

索引也要维护。并且索引越多,维护成本越高。

十六、索引优化建议

16.1 高频查询字段建索引

例如:

用户名
手机号
订单号

16.2 数据量小不需要索引

例如:

几十条数据

全表扫描更快。

16.3 区分度高的字段适合索引

例如:

手机号
身份证号

不适合:

性别

因为:

重复值太多

16.4 联合索引优于多个单列索引

推荐:

(name,age)

而不是:

name
age

16.5 尽量使用覆盖索引

减少回表。

十七、JavaWeb中的索引优化场景

17.1 登录功能

SELECT * FROM user
WHERE username=?;

username 应加索引。

17.2 商品搜索

SELECT * FROM product
WHERE category_id=?;

商品分类应加索引。

17.3 订单查询

SELECT * FROM orders
WHERE user_id=?
ORDER BY create_time DESC;

推荐联合索引:

(user_id,create_time)

十八、面试高频问题

18.1 为什么索引能提高查询效率?

因为减少了数据扫描次数。

18.2 MySQL索引底层是什么?

B+Tree

18.3 聚簇索引和非聚簇索引区别?

聚簇索引:

数据和索引在一起

非聚簇索引:

索引存主键值
需要回表

18.4 什么是回表查询?

先查普通索引:

再查主键索引。

18.5 什么是最左前缀原则?

联合索引必须从最左边字段开始使用。

十九、总结

索引是 MySQL 性能优化的核心。

它的本质:

帮助数据库快速查找数据

重点一定要掌握:

  • B+树

  • 聚簇索引

  • 联合索引

  • 最左前缀

  • 覆盖索引

  • 索引失效

对于开发者来说,真正的高性能系统:

并不是:

代码写得多复杂

而是:

SQL是否高效
索引是否合理

数据库性能,往往决定整个系统的性能上限。

到此这篇关于MySQL索引原理、分类与优化实战的文章就介绍到这了,更多相关MySQL索引原理、分类与优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql中 redo日志详解

    mysql中 redo日志详解

    mysql都会把回滚时所需的东西记录下来,这些为了回滚而记录的东西称之为撤销日志,也就是我们今天要讲的undo日志,下面我们就来聊一聊这个undo日志,感兴趣的朋友跟随小编一起看看吧
    2024-06-06
  • MySQL之复合查询解读

    MySQL之复合查询解读

    本文系统讲解SQL查询技术,涵盖基本查询(条件筛选、排序、聚合)、多表连接、自连接、子查询(单行/多行/多列)及合并查询(UNION/UNION ALL),通过emp、dept、salgrade三张表演示员工与部门数据关联分析方法
    2025-08-08
  • mysql删除表中某一字段重复的记录

    mysql删除表中某一字段重复的记录

    一般大家也许会碰到这个问题,大家可以参考下,讲的比较详细
    2008-07-07
  • 一文弄懂MySQL自增主键

    一文弄懂MySQL自增主键

    这篇文章主要介绍了MySQL自增主键,MySQL的自增主键并不一定是连续的,自增值的保存位置和修改机制决定了一种自增值不连续的场景,下面就来具体介绍一下,感兴趣的可以了解一下
    2025-01-01
  • MySQL自增锁(Auto-Increment Lock) 的原理使用

    MySQL自增锁(Auto-Increment Lock) 的原理使用

    MySQL的自增锁用于确保自增值在并发插入时唯一且递增,本文主要介绍了MySQL自增锁的原理使用,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • MySQL8.2.0安装教程分享

    MySQL8.2.0安装教程分享

    这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤
    2025-02-02
  • Mysql官方性能测试工具mysqlslap的使用简介

    Mysql官方性能测试工具mysqlslap的使用简介

    mysqlslap随着MySQL安装的时候就自动安装好了,而且 mysqlslap 把很多的自定义测试的功能封装到了外部,使用者只需要在外部提供 SQL 语句的脚本就可以自定义测试语句,本文将简单介绍该工具的使用
    2021-05-05
  • mysql线上查询前要注意资源限制的实现

    mysql线上查询前要注意资源限制的实现

    在数据库管理中,限制查询资源是避免单个查询消耗过多资源导致系统性能下降的重要手段,本文就来介绍了mysql线上查询前要注意资源限制的实现,感兴趣的可以了解一下
    2024-10-10
  • mysql 5.6.37(zip)下载安装配置图文教程

    mysql 5.6.37(zip)下载安装配置图文教程

    这篇文章主要为大家详细介绍了mysql 5.6.37(zip)下载安装配置图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • MySQL数据库给表添加索引的实现

    MySQL数据库给表添加索引的实现

    在MySQL中,索引是用来加速数据库查询的一种特殊数据结构,当我们需要查询数据库中某些数据的时候,如果数据库中有索引,就可以避免全表扫描,从而提高查询速度,本文就介绍了如何给表添加索引,感兴趣的可以了解一下
    2023-08-08

最新评论