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

《Java 100 天进阶之路》第83篇:MySQL索引(2026版)

第83篇:MySQL索引(2026版)

📌系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第82篇:Spring面试压轴题(待发布) |
➡️ 下一篇:第84篇:MySQL事务与锁(待发布


一、核心知识点

  • 索引本质:排好序的快速查找数据结构
  • B+Tree 索引:MySQL InnoDB 默认索引结构,叶子节点存储数据,非叶子节点存索引
  • 聚簇索引 vs 二级索引:聚簇索引叶子存整行数据,二级索引叶子存主键值
  • 回表:二级索引查到主键后,再到聚簇索引查完整行
  • 覆盖索引:索引列包含查询所需的所有字段,无需回表
  • 最左前缀原则:联合索引从左到右匹配,跳过中间列则后面失效
  • 索引下推(ICP):MySQL 5.6+,在索引遍历时直接过滤,减少回表次数
  • 索引失效场景:函数操作、隐式类型转换、%开头的模糊查询等
  • MySQL 8.0+ 新特性:隐藏索引、降序索引、索引统计信息持久化

二、通俗讲解(1分钟开心学)

1. 索引是什么?

索引是数据库的“目录”。没有索引就像一本没有目录的书,要找某句话只能一页页翻(全表扫描);有了索引,直接翻到对应页码即可。

生活类比
图书馆的图书分类标签(索书号)就是索引。你要找《Java编程思想》,先查电脑(索引)得到索书号 TP312JA/123,然后直接去书架定位,不用逛遍整个图书馆。

2. B+Tree 为什么适合数据库?

B+Tree 特点:

  • 非叶子节点只存索引,不存数据,能存放更多索引项,降低树高度(一般 2~4 层)。
  • 叶子节点形成双向链表,支持范围查询和顺序遍历。
  • 数据均匀分布在叶子节点,查询稳定(任何查找都 O(logN))。

对比其他数据结构

  • Hash 索引:单点查询快,但不支持范围查询,仅 Memory 引擎默认。
  • 二叉树:可能退化成链表,树高不可控。
  • B-Tree:非叶子也存数据,导致每层能存的索引变少,树更高。

3. 聚簇索引 vs 二级索引

  • 聚簇索引:叶子节点存储整行数据。InnoDB 中主键就是聚簇索引;没有主键则第一个 NOT NULL UNIQUE 列;都没有则隐式生成 rowid。
  • 二级索引(辅助索引):叶子节点存储主键值,查询时先找到主键,再到聚簇索引回表取完整数据。

生活类比
聚簇索引就像按学号排好的学生档案柜,学号对应整套档案。二级索引就像按姓名建的索引卡,上面写着学号,你需要根据学号再去档案柜取档案(回表)。

4. 最左前缀原则

联合索引(a, b, c)相当于按 a 排序,a 相同时按 b 排序,b 相同时按 c 排序。查询时从索引最左边开始匹配,跳过中间列则后续无法使用。

  • WHERE a = 1 AND b = 2 AND c = 3:全用
  • WHERE a = 1 AND b = 2:用 a、b
  • WHERE a = 1:用 a
  • WHERE b = 2:无法使用(跳过了 a)
  • WHERE a = 1 AND c = 3:只用 a,c 失效

三、实操代码案例 + 场景说明

测试表:用户订单表,数据量 100 万。

CREATETABLE`orders`(`id`bigint(20)NOTNULLAUTO_INCREMENT,`user_id`int(11)NOTNULL,`order_no`varchar(32)NOTNULL,`amount`decimal(10,2)DEFAULTNULL,`status`tinyint(4)DEFAULT'0',`create_time`datetimeDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(`id`),KEY`idx_user_status`(`user_id`,`status`),KEY`idx_order_no`(`order_no`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;
3.1 使用 EXPLAIN 分析执行计划
-- 1. 有效索引EXPLAINSELECT*FROMordersWHEREuser_id=123ANDstatus=1;-- type: ref, key: idx_user_status, rows: 很小-- 2. 索引失效(跳过左侧)EXPLAINSELECT*FROMordersWHEREstatus=1;-- type: ALL(全表扫描)-- 3. 索引失效(隐式类型转换)EXPLAINSELECT*FROMordersWHEREorder_no=123;-- order_no 是 varchar,传入 int-- key: NULL(不会用 idx_order_no)-- 4. 索引失效(函数操作)EXPLAINSELECT*FROMordersWHEREDATE(create_time)='2026-01-01';-- key: NULL-- 5. 覆盖索引(无需回表)EXPLAINSELECTuser_id,statusFROMordersWHEREuser_id=123;-- Extra: Using index
3.2 索引下推优化(ICP)

MySQL 5.6+ 默认开启。对于idx_user_status (user_id, status)

SELECT*FROMordersWHEREuser_id=123ANDstatus=1;

没有 ICP:先在二级索引找到 user_id=123 的所有主键(可能几百个),再回表读取完整行,再判断 status=1。
有 ICP:在二级索引遍历时直接判断 status=1,不匹配的就不回表,大幅减少回表次数。

3.3 排序与索引
-- 索引能支持排序,避免 filesortEXPLAINSELECT*FROMordersWHEREuser_id=123ORDERBYstatus;-- Extra: Using index condition(无 filesort)-- 索引不能支持排序(跳过了 user_id)EXPLAINSELECT*FROMordersORDERBYstatus;-- Extra: Using filesort
3.4 MySQL 8.0+ 新特性:隐藏索引与降序索引
-- 隐藏索引:不被优化器使用,用于测试删除影响ALTERTABLEordersALTERINDEXidx_user_status INVISIBLE;-- 再次查询,观察是否走索引-- 降序索引:联合索引中指定降序CREATEINDEXidx_user_create_descONorders(user_idASC,create_timeDESC);-- 适用于 ORDER BY user_id ASC, create_time DESC 场景

四、避坑要点(高频失效场景)

错误写法原因正确做法
WHERE status = 1联合索引跳过最左列建立 status 单独索引,或带上 user_id
WHERE order_no = 123隐式类型转换(varchar → int)应用层类型匹配:order_no = '123'
WHERE LEFT(name,3) = 'abc'函数操作破坏索引改用name LIKE 'abc%',或冗余存储
WHERE create_time + 1 = ...列参与运算改为create_time = ... - 1
WHERE name LIKE '%abc'前模糊匹配尽量放后面LIKE 'abc%',或使用倒排索引/ES
OR连接不同列可能不走索引拆分为 UNION,或用IN替代
!=<>范围查询,大概率全表考虑业务重构,或用><
IS NULL/IS NOT NULL某些情况不走索引根据实际数据分布,必要时建索引
统计信息过期优化器选择错误执行计划ANALYZE TABLE更新统计信息
在线加索引未注意 MDL 锁短暂阻塞写操作使用ALGORITHM=INPLACE, LOCK=NONE

五、面试高频考点

Q1:什么是回表?如何避免?

二级索引查到主键后,再到聚簇索引查询完整行的过程。
避免方法:使用覆盖索引(索引包含查询所需所有字段),或直接查主键。

Q2:最左前缀原则是什么?举例说明。

联合索引从左到右匹配,跳过中间列则后续无效。
例如索引(a, b, c),条件a=1 AND c=1只用到 a,c 失效。
原因是索引排序规则。

Q3:为什么用 B+Tree 而不用 B-Tree 或 Hash?

  • B+Tree:非叶子只存索引,叶子存数据且形成链表,树矮、范围查询快。
  • B-Tree:非叶子也存数据,层数更高,I/O 更多。
  • Hash:单点查询 O(1),但不支持范围、排序、模糊查询。

Q4:索引下推(ICP)是什么?

MySQL 5.6+,在索引遍历时直接过滤条件,减少回表次数。
仅适用于二级索引,且条件列在索引中。

Q5:如何设计联合索引?

原则:区分度高的列在前;等值查询列在前,范围查询列在后;考虑排序需求。
示例:where a=1 and b>2 order by c,建议索引(a, c)避免 filesort。

Q6:主键为什么建议自增?

自增主键保证插入时顺序写入,减少页分裂;
UUID 主键随机插入,页分裂频繁,导致索引碎片,性能差。

Q7:在线加索引会导致锁表吗?

MySQL 5.6+ 支持 Online DDL(ALGORITHM=INPLACE, LOCK=NONE),
主库加索引不阻塞写,但仍有短暂元数据锁(MDL)。
生产环境建议在低峰期操作。

Q8:MySQL 优化器如何选择索引?

基于索引统计信息(Cardinality,索引唯一值数量)。
如果统计信息过期,优化器可能误判,导致用错索引。
执行ANALYZE TABLE可更新统计信息。
MySQL 8.0+ 将统计信息持久化,减少问题发生。

Q9:什么是隐藏索引(Invisible Index)?

MySQL 8.0 引入,可设置索引对优化器不可见,但 DML 仍维护索引。
用于测试删除索引的影响,避免直接删除后重建的麻烦。

Q10:索引与锁的关系?

在不走索引的UPDATE/DELETE中,InnoDB 会锁全表(实际是锁所有聚簇索引扫描到的行)。
走索引则只锁索引覆盖的行,减少锁冲突。


六、练习题

  1. 分析:有一张订单表,查询SELECT * FROM orders WHERE user_id=123 ORDER BY create_time DESC LIMIT 10,如何建索引最优?

    💡 思路:
    等值查询(user_id)放在前面,排序(create_time)放在后面:(user_id, create_time),可同时支持过滤和排序,避免 filesort。

  2. 案例:某慢查询日志显示SELECT id,name,age FROM user WHERE name LIKE '%张%',耗时 5 秒,如何优化?

    💡 思路:前模糊无法走普通索引,可用倒排索引(存储反转字符串)或 Elasticsearch,或改用搜索引擎。

  3. 代码:使用EXPLAIN分析你项目中的一条慢查询,找出优化点。


📊 你的学习进度

  • 当前:第83篇 / 共108篇 ·进阶篇:数据库与持久层框架(第83~90篇)
  • ✅ 已完成:基础篇44篇 + 第91~96篇(Redis/MQ)+ 第83篇
  • 📖 正在学:第83篇
  • ⏳ 待学习:第84~90篇(MySQL 事务/锁/SQL优化/MyBatis)+ 第97~108篇(微服务/物联网/AI/设计模式/面试压轴)

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!


👉 下一篇文章预告

《第84篇:MySQL事务与锁(2026版)》

内容简介:事务四大特性(ACID)、隔离级别(读未提交→读已提交→可重复读→串行化)、MVCC 原理、间隙锁与幻读、死锁排查与解决。

💡 学完这篇,你将彻底搞懂 MySQL 并发控制,面试不再怕“RR 如何解决幻读”。

🎁福利提醒:评论区留言“MySQL索引”可领取《MySQL 索引优化实战清单》PDF。

📌《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!

http://www.gsyq.cn/news/1505206.html

相关文章:

  • Claudian插件与项目规划:AI辅助的任务管理
  • okbiye AI 毕业论文写作:三步标准化创作,一站式抚平应届毕业生全流程写作焦虑
  • 终极指南:如何用开源3D建模软件从照片创建专业级三维模型
  • 卡梅德生物科普:C5(补体蛋白C5)靶点功能与应用深度解析
  • 2026年6月青岛婚纱照品牌推荐:TOP10口碑严选+全攻略 - 江湖评测
  • 3大核心技术深度解析:cim系统如何实现高可用分布式即时通讯
  • 2026港大本科直申中介怎么挑?专业口碑佳、录取实力强的香港本科留学机构盘点 - 品牌2026
  • PowerPC EC603e嵌入式处理器硬件设计实战:从架构解析到PCB布局与调试
  • 别再死记硬背网络结构了!手把手带你用PyTorch复现GoogLeNet(附完整代码与调试技巧)
  • PCA9622 LED驱动器:两级PWM控制、I2C通信与热管理设计详解
  • 深入解析NXP PCA85262 LCD驱动芯片:低复用率原理与I2C配置实战
  • 如何安全备份微信聊天记录?WeChatExporter帮你实现本地数据永久保存
  • 2026达州企业业主高频选择的 5 家危房检测房屋结构安全鉴定机构实地测评整理 - 科信检测
  • 深入解析PCA9538A I2C GPIO扩展芯片:时序、焊接与PCB设计实战
  • phpClickHouse监控与诊断:如何使用系统表和查询日志进行性能分析
  • 深入解析MPC875/870通信处理器:架构、硬件设计与实战优化
  • PCA9500焊接工艺全解析:HVQFN封装回流焊实战指南
  • 如何使用PKSM:从第一代到第八代口袋妖怪存档管理终极指南
  • 2026 避坑|厦门正规回收:只看克重纯度,不看品牌小票 - 奢侈品回收评测
  • 解锁跨平台音乐自由:洛雪音乐助手桌面版终极使用指南
  • 攻克嵌入式开发痛点:在VSCode/Vim+clangd中精准配置交叉编译器的系统头文件
  • PCA9629A I2C步进电机控制器:硬件卸载与精确运动控制实战
  • NX C语言二次开发:UF_CURVE_create_spline样条创建函数实战包(含多版本适配代码与错误处理)
  • 终极Microsoft.UI.Xaml指南:从零构建现代化Windows应用
  • 小米手表表盘设计终极指南:零基础快速制作个性表盘的完整教程
  • 如何选择最适合你的Windows压缩工具?NanaZip现代化文件管理解决方案深度解析
  • 虚拟阵列扩展:从四阶累积量到内插外推的孔径增强实践
  • 2026成都第三方仓储公司推荐榜 按需挑选不踩雷 - 资讯速览
  • HC32F460 ADC配置实战:从电位器采样到代码解析
  • 合肥人注意!2026黄金回收行情解析,教你高位稳妥变现 - 奢侈品回收评测