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

MySQL 专题(二):索引原理与优化

MySQL 专题(二):索引原理与优化

在这里插入图片描述

在 MySQL 性能优化中,索引 是最核心的工具之一。它就像一本书的目录,可以帮我们快速定位数据,而不用一页一页去翻。

今天这篇文章我们会分两部分:

  1. 索引的底层原理(B+ 树)
  2. SQL 优化与索引的正确使用

一、B+ 树:MySQL 索引的底层原理

在 MySQL 的 InnoDB 存储引擎中,索引底层结构是 B+ 树

1. B+ 树结构示意

假设我们在 user(id, name, age) 表的 id 字段上建立了主键索引,B+ 树结构大致如下:

                       [100 | 500 | 900]    ← 根节点(索引目录)/         |         \[1..99] [100..499] [500..899] [900..∞]  ← 中间节点|         |           |          |┌─────────┴─────────┘           |          |↓                               ↓          ↓
[id=10,data] - [id=50,data] ... [id=499,data] ... [id=899,data] ... [id=1200,data]↑───────────────────────────────↑───────────────────────────────↑───────────────叶子节点(存储整行数据)        叶子节点之间通过链表连接(范围查询超快)

👉 特点:

  • 根节点 & 中间节点 只存“目录 key”,不存实际数据。
  • 所有数据都在叶子节点
  • 叶子节点之间有链表,支持范围扫描 (BETWEEN, ORDER BY)。

2. 查询过程示例

  • 查询 id = 500

    1. 根节点定位 [500..899] 区间
    2. 进入中间节点找到 500
    3. 进入叶子节点,取整行数据
      👉 只需 3 次磁盘 IO。
  • 范围查询 200 ≤ id ≤ 600

    1. 定位到 200 的叶子节点
    2. 沿着叶子链表顺序扫描到 600
      👉 效率极高,比普通 B 树快。

3. 为什么选择 B+ 树而不是哈希索引或二叉树?

  • B+ 树 vs 二叉树

    • 二叉树深度大,磁盘 IO 次数多;
    • B+ 树扇出大(每个节点能容纳很多 key),层数更少,查询更快。
  • B+ 树 vs Hash 索引

    • 哈希索引只适合等值查询(=),不支持范围查询;
    • B+ 树既支持等值查找,也支持范围查找。

👉 总结:B+ 树是 MySQL 索引的最佳平衡点


二、SQL 优化与索引使用

理解了 B+ 树原理后,我们就能更好地写“索引友好”的 SQL。否则,即使建了索引,也可能失效。

1. 索引失效的常见场景

  • (1) 对索引列做运算
SELECT * FROM user WHERE age + 1 = 30;

❌ 失效(age+1 破坏索引)。
✅ 改写:

SELECT * FROM user WHERE age = 29;

  • (2) 使用函数处理索引列
SELECT * FROM user WHERE DATE(create_time) = '2025-09-12';

❌ 失效。
✅ 改写范围:

SELECT * FROM user 
WHERE create_time >= '2025-09-12 00:00:00'AND create_time <  '2025-09-13 00:00:00';

  • (3) 模糊查询前缀 %
SELECT * FROM user WHERE name LIKE '%Tom';

❌ 前缀 % 导致全表扫描。
✅ 优化:

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

或使用全文索引。


  • (4) OR 条件
SELECT * FROM user WHERE id=10 OR age=20;

❌ 索引失效。
✅ 改写:

SELECT * FROM user WHERE id=10
UNION
SELECT * FROM user WHERE age=20;

  • (5) 类型不匹配
SELECT * FROM user WHERE phone = 13888888888;

❌ phone 是字符串,但没加引号 → 索引失效。
✅ 改写:

SELECT * FROM user WHERE phone = '13888888888';

2. 覆盖索引(Covering Index)

如果查询只涉及索引列,就不需要“回表”。

  • 覆盖索引查询:
SELECT id, name FROM user WHERE id=100;

👉 只查索引,不访问数据页,性能极高。

  • 非覆盖索引查询:
SELECT id, name, age FROM user WHERE id=100;

👉 需要回表取 age,多一次 IO。


3. 最左前缀原则

联合索引 (a, b, c) 的使用规则:

  • aa,ba,b,c
  • ❌ 单独用 bc
SELECT * FROM user WHERE b=10;  -- 索引无效

👉 建索引时要根据 查询习惯,把过滤最常用、区分度最高的列放在前面。


4. 索引选择性

索引的效果取决于 区分度(不同值的数量)。

  • 性别 gender 只有男/女 → 区分度低,不适合建索引。
  • 身份证号 id_number 唯一值很多 → 区分度高,适合建索引。

三、总结

  1. MySQL 索引的底层是 B+ 树,数据存放在叶子节点,叶子之间通过链表连接,非常适合范围查询。
  2. 索引的高效利用依赖 写法:避免函数、运算、前缀 %、OR、类型转换。
  3. 覆盖索引最左前缀原则 是写高性能 SQL 的关键。
  4. 索引要建在 区分度高的列 上,才能真正提升性能。

👉 一句话总结:
理解 B+ 树原理,写出索引友好的 SQL,你的 MySQL 性能优化就成功了一大半。


在这里插入图片描述

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

相关文章:

  • 【脑电分析系列】第17篇:EEG特征提取与降维进阶 — 主成分分析、判别分析与黎曼几何
  • NVIDIA DOCA 环境产品使用与体验报告
  • C# Windows Service 中添加 log4net 的详细教程
  • 用 pymupdf4llm 打造 PDF → Markdown 的高效 LLM 数据管道(附实战对比)
  • 机械设备钢材建材网站 网站模版
  • Mysql8 SQLSTATE[42000] sql_mode=only_full_group_by错误解决办法
  • 【第五章:计算机视觉-项目实战之图像分类实战】2.图像分类实战-(3)批量归一化(Batch Normalization)和权重初始化的重要性
  • SQL Server 多用户读写随机超时?从问题分析到根治方案
  • 2.css的继承性,层叠性,优先级
  • OpenStack 学习笔记(四):编排管理与存储管理实践(上)
  • list_for_each_entry 详解
  • Perplexity AI Agent原生浏览器Comet
  • 颈椎按摩器方案开发,智能按摩仪方案设计
  • Sui 学习日志 1
  • 六、Java—IO流
  • 数据库 事务隔离级别 深入理解数据库事务隔离级别:脏读、不可重复读、幻读与串行化
  • 从“纸面”到“人本”:劳务合同管理的数字化蜕变
  • ARM架构——学习时钟7.2
  • VS Code 调试配置详解:占位符与语言差异
  • 锁 相关知识总结
  • caffeine 发生缓存内容被修改以及解决方案-深度克隆
  • rust编写web服务06-JWT身份认证
  • 《怪猎:荒野》制作人:PC平台对日本游戏非常重要
  • 大模型训练框架(二)FSDP
  • MySQL——系统数据库、常用工具
  • 蓝桥杯题目讲解_Python(转载)
  • 性能测试监控实践(九):性能测试时,监控docker微服务资源利用率和分析
  • TCP,UDP和ICMP
  • Python语法学习篇(七)【py3】
  • 网页控制鼠标 查看鼠标位置