从零起步学习MySQL || 第八章:索引深入理解及高级运用(结合常见优化问题讲解)

一、为什么要创建索引(Index)?

索引的作用:

索引就像一本书的"目录",让数据库在查询数据时可以"快速定位"记录,而不是全表扫描。

优点:

  • 大大提高数据检索速度

  • 加快表之间的连接(join)

  • 在分组(GROUP BY)、排序(ORDER BY)时也能提高效率

缺点:

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

  • 插入、删除、更新数据时,索引也要维护,可能会变慢


二、什么时候需要创建索引

可以简单理解为一句话:

"凡是经常出现在 WHEREJOINORDER BYGROUP BY 的列,都值得考虑建立索引。"

具体场景:

  1. 主键和唯一键

    • 主键会自动创建唯一索引。

    • 唯一键(UNIQUE)可以保证数据唯一性。

  2. 经常用作查询条件的字段

    复制代码
    SELECT * FROM user WHERE email = 'test@xupt.edu.cn';

    应给 email 创建索引。

  3. 用于排序的字段

    复制代码
    SELECT * FROM article ORDER BY create_time DESC;

    create_time 建索引可避免文件排序。

  4. 用于分组统计的字段

    复制代码
    SELECT department, COUNT(*) FROM employee GROUP BY department;

    department 列可建索引。

  5. 多表连接时用作连接条件的字段

    复制代码
    SELECT * FROM student s JOIN score c ON s.id = c.student_id;

    student.idscore.student_id 都应建索引。


三、什么时候不需要创建索引

索引不是越多越好,错误的索引会拖慢性能。

不建议建索引的情况:

  1. 数据量很小的表

    • 比如只有几百行,MySQL 直接全表扫描更快。
  2. 频繁更新的字段

    • 每次更新都要维护索引,会拖慢性能。
  3. 高重复度的字段

    • 如"性别"、"是否删除(0/1)",区分度太低。

    • 索引选择性低,优化效果几乎没有。

  4. 查询中很少用到的字段

    • 从不出现在 WHEREORDER BYGROUP BY 中的列没必要建索引。

四、索引优化方法

接下来讲几个常见的索引优化技巧,在面试中也经常被问到


1️⃣ 前缀索引优化(Prefix Index)

当字符串字段太长(如邮箱、URL、UUID)时,索引整个字段会浪费空间。

可以只取前几个字符建立索引。

复制代码
ALTER TABLE user ADD INDEX idx_email (email(10));

优点:

  • 占用空间小,比较速度快。

缺点:

  • 可能降低"区分度",MySQL 仍可能要回表验证。

实战建议:

SELECT COUNT(DISTINCT LEFT(email, N)) / COUNT(*) 来测试前缀长度的区分度。


2️⃣ 覆盖索引优化(Covering Index)

"覆盖索引"指的是查询的字段都在索引中,不用回表读取数据。

复制代码
-- 索引包含 (id, name)
SELECT id, name FROM student WHERE id = 1;

优点:

  • 避免回表(减少IO),查询更快。

优化手段:

只查需要的字段;用 EXPLAIN 查看 Extra 字段中是否有 Using index


3️⃣ 主键索引自增优化(Auto Increment Primary Key)

InnoDB 的主键索引是聚簇索引(Clustered Index) ,数据按照主键顺序存储。

如果主键是随机的(比如 UUID),容易导致数据页分裂、碎片多、写入慢。

建议:

复制代码
id BIGINT AUTO_INCREMENT PRIMARY KEY

自增主键能保证数据顺序插入,性能最优。


4️⃣ 索引列设置为 NOT NULL

MySQL 在处理 NULL 时无法高效使用索引(特别是范围查询、排序时)。

建议:

  • 避免在索引列中使用 NULL

  • 可以设置默认值,比如 DEFAULT ''DEFAULT 0


5️⃣ 防止索引失效的情况

索引建立了 ≠ 一定会被用到。

常见的"索引失效"场景如下

场景 例子 原因
使用 OR WHERE a=1 OR b=2 可能导致全表扫描
函数操作 WHERE YEAR(create_time)=2025 函数操作让索引失效
模糊匹配 % 开头 LIKE '%abc' 无法利用前缀索引
隐式类型转换 WHERE num = '123' 类型不同会触发转换
复合索引未遵守"最左前缀原则" 索引(a,b,c),只用 b 查询 无法使用索引

解决方法:

  • 保持字段类型一致

  • 避免对索引列进行计算或函数操作

  • 对字符串匹配尽量使用前缀匹配 LIKE 'abc%'

  • 使用复合索引时遵守"最左前缀原则"


五、总结速记表

类型 原则/技巧 说明
创建索引 WHERE / JOIN / ORDER / GROUP字段 提高查询效率
不建索引 小表 / 高频更新 / 低区分度字段 节省资源
前缀索引 email(10) 节省空间,需测试区分度
覆盖索引 查询字段全在索引中 避免回表
主键自增 AUTO_INCREMENT 防止页分裂
NOT NULL 索引列不应为NULL 提高效率
索引失效 函数、OR、%abc、类型不匹配 避免这些写法
相关推荐
疯狂踩坑人4 小时前
【深入浅出Nodejs】异步非阻塞IO
后端·node.js
Sam_Deep_Thinking4 小时前
为超过10亿条记录的订单表新增字段
mysql
奥尔特星云大使4 小时前
Docker 拉取 MySQL 5.7 镜像、启动容器并进入 MySQL
数据库·mysql·docker·容器
赵杰伦cpp4 小时前
C++的继承机制精讲
java·开发语言·c++·后端
aloha_4 小时前
LLM模型指令遵循偏差
后端
.ZGR.4 小时前
蓝桥杯高校新生编程赛第一场题解——Java
java·算法·蓝桥杯
gongzemin4 小时前
使用阿里云ECS部署Express
后端·node.js·express
高德开放平台4 小时前
实战案例|借助高德开放平台实现智慧位置服务:路线导航的开发与实践
前端·后端
KubeSphere4 小时前
在 KubeSphere 上构建你的自托管 AI 助手|Open WebUI 扩展上线
后端