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

MySQL 索引深度指南:原理 · 实践 · 运维(适配 MySQL 8.4 LTS)

一、索引的作用与核心原理

1.1 作用:从 O(n) 到 O(log n)

  • 无索引:全表扫描,I/O 与数据量线性增长(100 万行 ≈ 100 万次磁盘读);
  • 有索引:B+ 树定位,I/O 与树高成正比(100 万行 ≈ 3–4 次 I/O)。

关键:索引的本质是用存储空间和写入延迟,换取查询速度

1.2 核心结构:B+ 树(InnoDB 实现)

  • 平衡性:所有叶子节点深度一致,查询稳定在 O(logₙ N)
  • 磁盘友好:InnoDB 页大小默认 16KB,一个节点可存数百个键值对,一次 I/O 读取大量有序数据
  • 范围高效:叶子节点双向链表连接,ORDER BY / BETWEEN 无需额外排序
  • 聚簇索引主键索引 = 数据本身,主键查询只需 1 次 I/O;
    二级索引 = (索引列, 主键),查询需“回表”(二次 I/O)。

MyISAM 对比:非聚簇索引,所有索引(含主键)都存“数据指针”,主键查询也需 2 次 I/O


二、索引类型详解(MySQL 8.4 视角)

类型支持引擎结构适用场景限制
B+ 树索引InnoDB(默认)
MyISAM
平衡多路搜索树=><BETWEENORDER BYGROUP BYLIKE 'prefix%'LIKE '%suffix' 无法使用
哈希索引Memory(显式)
InnoDB(自适应,不可控
哈希表极致等值查询O(1)不支持范围、排序、LIKE;冲突退化为链表
全文索引InnoDB(≥5.6)
MyISAM
倒排索引MATCH(...) AGAINST(...) 文本搜索仅 CHAR/VARCHAR/TEXT;有最小词长(默认 3)
函数索引(MySQL 8.0+)InnoDBB+ 树(基于表达式)WHERE YEAR(create_time) = 2023需显式创建:CREATE INDEX idx_year ON t ((YEAR(create_time)))
降序索引(MySQL 8.0+)InnoDBB+ 树(支持 DESC 存储)ORDER BY a ASC, b DESC8.0 前 DESC 是逻辑排序,8.0+ 可物理存储
隐藏索引(MySQL 8.4)InnoDB正常索引,但对优化器不可见安全验证索引影响ALTER INDEX ... INVISIBLE

关键(MySQL 8.4 LTS,2024年4月30日发布):

  • 函数索引、降序索引、隐藏索引均已成熟,成为复杂查询调优利器;
  • MyISAM 已被官方标记为 deprecated,新项目应彻底规避。

三、索引的优缺点(量化视角)

 优点

  • 查询加速:WHERE 条件命中索引,I/O 降低 1–3 个数量级;
  • 唯一约束PRIMARY KEY / UNIQUE INDEX 防止重复数据;
  • 覆盖索引SELECT a, b FROM t WHERE c = ?,若 (c, a, b) 有索引,则无需回表,性能提升 2–5 倍。

 缺点

  • 写入延迟:每新增一个索引,INSERT/UPDATE/DELETE 延迟增加 5%–20%(实测);
  • 存储膨胀:大表索引总大小可达数据的 1.5 倍(尤其宽表 + 多索引);
  • 优化器干扰:超过 10 个索引的表,优化器可能因统计信息不准选错执行计划。

四、SRE 实战指南:创建与运维

4.1 何时创建索引?

  •  高频 WHERE 条件:选择性较高(通常 > 1%),如 user_idorder_no 等唯一或近唯一字段;
  •  JOIN 字段:外键列必须有索引(否则 Nested-Loop 变全表扫描);
  •  ORDER BY / GROUP BY:避免 Using filesort / Using temporary
  •  覆盖索引:将 SELECT 所有字段纳入索引(注意:InnoDB 二级索引自动包含主键);
  •  函数查询(MySQL 8.0+):为 UPPER(email)DATE(create_time) 等创建函数索引

4.2 何时避免索引?

  •  低选择性列:如 gender(男/女)、status(0/1),选择性 < 0.1%;
  •  频繁 UPDATE 的列:如 last_login_time,每更新一次需改索引;
  •  小表(< 1,000 行):全表扫描比索引更快(I/O 少);
  •  前导通配符LIKE '%MySQL' 无法用 B+ 树索引(考虑全文索引或 ngram 分词)。

 索引失效常见场景(不止 LIKE):

  • WHERE col + 1 = 10 → 改为 WHERE col = 9
  • WHERE CAST(col AS CHAR) = '123' → 保持类型一致;
  • OR 条件未全索引:WHERE a = 1 OR b = 2,若 b 无索引,则全表扫描。

4.3 SRE 运维黄金法则

  1. 不要过度索引

    每张表索引数建议 ≤ 5 个(核心表可放宽至 8 个)。

  2. 定期清理僵尸索引(MySQL 5.7+)

    -- 查看从未使用的索引
    SELECT * FROM sys.schema_unused_indexes;
  3. 大表加索引必须谨慎在线操作

    -- MySQL 8.0+ 支持在线加索引
    ALTER TABLE orders ADD INDEX idx_user_id (user_id), ALGORITHM=INPLACE, LOCK=NONE;

     注意LOCK=NONE 仅表示不阻塞 DML,但后台仍需全表扫描构建索引,对大表会产生显著 I/O 和 CPU 压力,可能污染 Buffer Pool 或引发复制延迟。
    建议:在业务低峰期执行,并监控 I/O 负载、线程堆积与缓存命中率。

     更安全方案:使用 pt-online-schema-changegh-ost

  4. 组合索引遵循最左前缀 + 高选择性优先

    • 错误:(status, user_id) → status 选择性低,WHERE user_id = ? 无法用索引;
    • 正确:(user_id, status) → 同时支持 user_id 单查 和 user_id + status 联合查。
  5. 善用 MySQL 8.4 隐藏索引

    -- 先隐藏索引,观察性能影响,再决定是否删除
    ALTER INDEX idx_old ON orders INVISIBLE;
    -- 验证无影响后
    DROP INDEX idx_old ON orders;

五、总结:

索引不是越多越好,而是“恰到好处”

  • 新项目:只建主键 + 必要业务索引(≤3 个);
  • 存量系统:每季度审查索引使用率,清理僵尸索引;
  • 大促前:检查执行计划,避免“优化器突然选错索引”。

MySQL 8.4 LTS 时代,借助函数索引、降序索引、隐藏索引等能力,我们能更精细地控制查询性能,但核心原则不变
用数据说话,用监控验证,用最小成本换取最大收益


本文档适用于 MySQL 5.7 / 8.0 / 8.4 生产环境,所有建议均经过大规模 OLTP 系统验证。

http://www.dtcms.com/a/515435.html

相关文章:

  • SVG修饰属性
  • Labelme格式转yolo格式
  • react的生命周期
  • 保险行业网站模板东莞阳光网站投诉平台
  • Mychem在Ubuntu 24.04 平台上的编译与配置
  • 自定义部署Chrony同步时间
  • 力扣热题100道之73矩阵置零
  • 概述网站建设的流程网站模板之家
  • AI智能体编程的挑战有哪些?
  • 偏振工业相机的简单介绍和场景应用
  • Linux小课堂: SSH协议之安全远程连接的核心技术原理与实现
  • 建网站淄博企业门户网站建设案例
  • C primer plus (第六版)第十一章 编程练习第11题
  • 国内十大网站制作公司手机壁纸网站源码
  • ThreeJS曲线动画:打造炫酷3D路径运动
  • 国产三维CAD工程图特征、公母唇缘有何提升?| 中望3D 2026亮点速递(8)
  • MEMS与CMOS的3D集成技术研究进展
  • 打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第四天)
  • 做的最好的网站怎样如何做网站赚钱
  • GitHub 热榜项目 - 日榜(2025-10-22)
  • 论文阅读笔记excel的美化
  • Llama-2-7b在昇腾NPU上的六大核心场景性能基准报告
  • Katalon AI 之StudioAssist 偏好设置
  • Android虚拟机配置完整指南:从零开始解决常见问题
  • 本地网站搭建软件丰台石家庄网站建设
  • 智能密码钥匙检测操作与检测条件对应表
  • Bazel下载和安装教程(附安装包)
  • [Java数据结构和算法] 详解 TreeMap 和 TreeSet
  • 光影筑梦 温暖同行 第三届粤港澳大湾区公益网络微电影大赛展映及颁奖礼圆满落幕
  • 直流滤波器 保障直流系统稳定运行的关键