MySQL索引原理图文详解

一、索引的基本概念与作用

1.1 什么是索引?

索引是帮助MySQL高效获取数据的数据结构,类似于书籍的目录,可以快速定位到数据的位置

1.2 为什么需要索引?

  • 提高查询速度:避免全表扫描

  • 保证数据唯一性:唯一索引

  • 加速表连接:JOIN操作优化

  • 排序优化:ORDER BY、GROUP BY优化

1.3 索引的代价

  • 空间占用:索引需要额外的存储空间

  • 维护成本:DML操作需要更新索引

  • 优化器负担:需要选择合适的索引

二、索引的底层数据结构

2.1 B-Tree(平衡多路查找树)

text

[P1 | 20 | P2 | 50 | P3] / | \ / | \ [10|15] [25|30|35] [55|60|70]

特点

  • 所有叶子节点在同一层

  • 每个节点有多个子节点

  • 保证查找效率 O(log n)

2.2 B+Tree(MySQL主要索引结构)

text

┌─────────────────┐ │ 非叶子节点 │ │ [P1|20|P2|50|P3]│ └────────┬────────┘ ┌─────┼─────┐ │ │ │ ┌──────▼─┐ ┌─▼──────┐ ┌──────▼─┐ │叶子节点1│ │叶子节点2│ │叶子节点3│ │10→15→20│ │25→...→50│ │55→...→70│ └────┬───┘ └────┬───┘ └────┬───┘ │ │ │ ▼ ▼ ▼ 数据页 数据页 数据页

与B-Tree的区别

  • 非叶子节点只存键值,不存数据

  • 叶子节点包含所有键值数据指针

  • 叶子节点形成双向链表,支持范围查询

2.3 Hash索引

text

键值 → Hash函数 → Hash值 → 桶 → 链表存储数据指针

特点

  • O(1)查找效率

  • 只支持等值查询,不支持范围查询

  • Memory引擎支持

2.4 全文索引(FULLTEXT)

text

文档 → 分词 → 倒排索引 "我爱中国" → ["我", "爱", "中国"]

三、MySQL存储引擎与索引实现

3.1 InnoDB索引实现

聚簇索引(Clustered Index)

text

┌─────────────────────────────────────┐ │ B+Tree索引结构 │ │ │ │ 非叶节点: [键值+子节点指针] │ │ ↓ │ │ 叶子节点: [键值+整行数据] ← 数据就是这里! │ └─────────────────────────────────────┘

特点

  • 数据按主键顺序存储

  • 叶子节点存储完整行数据

  • 一个表只能有一个聚簇索引

  • 主键就是聚簇索引

二级索引(Secondary Index)

text

┌─────────────────────────────────────┐ │ B+Tree索引结构 │ │ │ │ 非叶节点: [索引列值+子节点指针] │ │ ↓ │ │ 叶子节点: [索引列值+主键值] → 需要回表! │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ 到聚簇索引查找完整数据 │ └─────────────────────────────────────┘

回表查询:通过二级索引找到主键,再通过主键到聚簇索引找完整数据

3.2 MyISAM索引实现

text

┌─────────────────────────────────────┐ │ B+Tree索引结构 │ │ │ │ 非叶节点: [键值+子节点指针] │ │ ↓ │ │ 叶子节点: [键值+数据行地址] → 指向数据文件 │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ .MYD数据文件[行数据] │ │ .MYI索引文件 │ └─────────────────────────────────────┘

特点

  • 索引和数据分开存储

  • 都是非聚簇索引

  • 叶子节点存储数据文件地址

四、索引类型详解

4.1 按功能分类

普通索引(INDEX)

sql

CREATE INDEX idx_name ON users(name);
  • 最基本的索引

  • 无任何限制

唯一索引(UNIQUE)

sql

CREATE UNIQUE INDEX uni_email ON users(email);
  • 保证列值唯一

  • 可以有NULL值

主键索引(PRIMARY KEY)

sql

ALTER TABLE users ADD PRIMARY KEY (id);
  • 特殊的唯一索引

  • 不允许NULL值

  • 一个表只能有一个

全文索引(FULLTEXT)

sql

CREATE FULLTEXT INDEX ft_content ON articles(content);
  • 用于全文搜索

  • 仅限CHAR、VARCHAR、TEXT类型

组合索引(复合索引)

sql

CREATE INDEX idx_name_age ON users(name, age);
  • 多列组成的索引

  • 遵守最左前缀原则

4.2 按物理存储分类

聚簇索引 vs 非聚簇索引
特性聚簇索引非聚簇索引
数据存储索引叶子节点存储数据索引叶子节点存储指针
数量每表1个每表多个
更新代价高(数据重排)
范围查询高效相对较慢

五、索引的使用原则

5.1 最左前缀原则

对于组合索引(A, B, C)

text

有效查询: ✓ WHERE A = 1 ✓ WHERE A = 1 AND B = 2 ✓ WHERE A = 1 AND B = 2 AND C = 3 ✓ WHERE A = 1 AND C = 3 # 只用到A 无效查询: ✗ WHERE B = 2 ✗ WHERE C = 3 ✗ WHERE B = 2 AND C = 3

5.2 索引覆盖

sql

-- 假设有索引 (name, age) SELECT name, age FROM users WHERE name = '张三'; -- 索引覆盖:数据直接从索引获取,无需回表

5.3 索引下推(ICP)

MySQL 5.6+引入的优化:

text

传统方式: 1. 使用索引定位到数据位置 2. 回表取出整行数据 3. 在Server层过滤数据 索引下推: 1. 使用索引定位 2. 在存储引擎层过滤 3. 只对符合条件的回表

5.4 索引失效场景

sql

-- 1. 对索引列进行运算 SELECT * FROM users WHERE YEAR(create_time) = 2023; -- 失效 SELECT * FROM users WHERE create_time >= '2023-01-01'; -- 有效 -- 2. 使用 NOT、!=、<>、NOT IN SELECT * FROM users WHERE name != '张三'; -- 可能失效 -- 3. 使用 OR 连接(除非所有列都有索引) SELECT * FROM users WHERE name = '张三' OR age = 20; -- 可能失效 -- 4. LIKE 以通配符开头 SELECT * FROM users WHERE name LIKE '%张%'; -- 失效 SELECT * FROM users WHERE name LIKE '张%'; -- 有效 -- 5. 隐式类型转换 SELECT * FROM users WHERE phone = 13800138000; -- phone是varchar,失效 -- 6. 使用函数 SELECT * FROM users WHERE LOWER(name) = 'zhangsan'; -- 失效

六、EXPLAIN执行计划详解

6.1 EXPLAIN关键字段

sql

EXPLAIN SELECT * FROM users WHERE name = '张三';
字段说明重要值
type访问类型system > const > eq_ref > ref > range > index > ALL
key使用的索引实际使用的索引名
rows预估扫描行数越小越好
Extra额外信息Using index, Using where, Using filesort等

6.2 type字段详解

text

查询效率从高到低: system:系统表,仅一行 const:通过主键或唯一索引查询 eq_ref:关联查询,主键或唯一索引 ref:非唯一索引查询 range:范围查询 index:全索引扫描 ALL:全表扫描(需要优化)

七、索引优化实战

7.1 选择合适的索引列

sql

-- 高选择性列适合建索引 SELECT COUNT(DISTINCT gender) / COUNT(*) FROM users; -- 选择性低 SELECT COUNT(DISTINCT email) / COUNT(*) FROM users; -- 选择性高 -- 为WHERE、JOIN、ORDER BY、GROUP BY的列建索引

7.2 避免过度索引

sql

-- 冗余索引示例 INDEX (A, B) -- 已经包含 INDEX (A) -- 冗余! -- 重复索引示例 UNIQUE (A) -- 唯一索引 INDEX (A) -- 重复!

7.3 使用索引排序

sql

-- 使用索引排序 SELECT * FROM users ORDER BY name; -- 如果name有索引,可以使用 -- 无法使用索引排序的情况 SELECT * FROM users ORDER BY name, age DESC; -- 混合排序方向 SELECT * FROM users WHERE name = '张三' ORDER BY age; -- 如果索引是(name, age),可用

八、高级索引技术

8.1 自适应哈希索引(AHI)

text

InnoDB自动为热点数据创建哈希索引 监控 → 检测热点数据 → 自动创建哈希索引

8.2 索引合并

sql

-- MySQL可能合并多个索引 SELECT * FROM users WHERE name = '张三' OR age = 20; -- 可能使用 name索引 + age索引,然后合并结果

8.3 前缀索引

sql

-- 为文本字段前N个字符创建索引 CREATE INDEX idx_email_prefix ON users(email(10)); -- 计算合适的前缀长度 SELECT COUNT(DISTINCT LEFT(email, 5)) / COUNT(*) as len5, COUNT(DISTINCT LEFT(email, 10)) / COUNT(*) as len10, COUNT(DISTINCT LEFT(email, 20)) / COUNT(*) as len20 FROM users;

九、索引设计最佳实践

9.1 设计原则

  1. 不是越多越好:每个索引都需要维护成本

  2. 经常查询的列:WHERE、JOIN、ORDER BY、GROUP BY

  3. 高选择性的列:区分度高的列

  4. 使用组合索引:减少索引数量

  5. 小字段优先:减少索引大小

  6. 避免更新频繁的列:增加维护成本

9.2 具体建议

sql

-- 1. 主键自增 CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, ... ); -- 2. 常用查询组合索引 CREATE INDEX idx_status_created ON orders(status, created_at); -- 3. 覆盖索引设计 -- 查询:SELECT id, name, age FROM users WHERE name LIKE '张%'; CREATE INDEX idx_name_age ON users(name, age); -- id是主键,自动包含 -- 4. 长字段使用前缀索引 CREATE INDEX idx_content ON articles(content(100));

9.3 监控与维护

sql

-- 查看索引使用情况 SELECT * FROM sys.schema_unused_indexes; -- 查看重复索引 SELECT * FROM sys.schema_redundant_indexes; -- 索引统计信息 SHOW INDEX FROM users; ANALYZE TABLE users; -- 更新统计信息

十、索引与锁机制

10.1 行锁与索引

sql

-- 没有索引:表锁 UPDATE users SET age = 20 WHERE name = '张三'; -- name无索引 → 锁全表 -- 有索引:行锁 UPDATE users SET age = 20 WHERE id = 100; -- id有主键索引 → 只锁该行

10.2 间隙锁(Gap Lock)

text

索引范围:10, 20, 30, 40, 50 UPDATE users SET ... WHERE age > 20 AND age < 40; 间隙锁锁定:(20, 30), (30, 40) 这两个区间 防止其他事务在这个范围内插入数据

总结

核心要点回顾:

  1. B+Tree是MySQL索引的核心数据结构

  2. InnoDB使用聚簇索引,数据和索引在一起

  3. 最左前缀原则是组合索引的黄金法则

  4. 索引覆盖可以避免回表,大幅提升性能

  5. 索引不是越多越好,需要权衡利弊

优化路线图:

text

1. 分析慢查询(slow log) 2. EXPLAIN查看执行计划 3. 检查索引使用情况 4. 设计合适的索引 5. 避免索引失效场景 6. 定期监控和维护

最后提醒:

  • 索引是双刃剑,合理使用才能发挥最大价值

  • 理论结合实践,根据实际业务调整

  • 测试环境充分验证后再上线

  • 监控生产环境索引使用情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1148457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1小时验证创意:用TRACKER服务器原型吸引投资人

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个具有可视化效果的TRACKER服务器原型&#xff0c;要求&#xff1a;1) 实时显示在线peer数和流量统计 2) 地理分布热力图 3) 生成漂亮的演示数据报表 4) 包含3种典型使用场景…

1小时验证创意:SpringBoot 4.0原型开发指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个物联网设备监控系统原型&#xff1a;1. 模拟10个传感器通过MQTT上报数据 2. SpringBoot 4.0处理消息并存储到时序数据库 3. 实时WebSocket推送数据 4. 可视化仪表盘&#…

南大通用Gbase 8c dblink功能使用简介

Gbase 8c 提供类似 Oracle 的 dblink 功能需要分布式集群版本 GBase8cV5 3.0.3B16 以上和主备集群 gbase8cV5 S5.0.0B24 以上版本使用。1、创建 dblink 远程连接需要创建用户密钥文件&#xff0c;该步骤可以忽略&#xff1a;gs_ssh -c "gs_guc generate -S db1x123 -D $GA…

企业级应用中的错误日志处理实战

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个企业级错误日志分析系统&#xff0c;功能包括&#xff1a;1. 实时监控日志中的意料之外的错误&#xff1b;2. 对LINE 1 - THIS LOG WAS CREATED WITHOUT ADVANCED COM类错…

告别复杂配置!一键部署MiDaS深度估计,轻松实现3D空间感知

告别复杂配置&#xff01;一键部署MiDaS深度估计&#xff0c;轻松实现3D空间感知 &#x1f310; 技术背景&#xff1a;从2D图像到3D空间理解的跨越 在计算机视觉领域&#xff0c;单目深度估计&#xff08;Monocular Depth Estimation&#xff09;是一项极具挑战性的任务——仅凭…

Rembg抠图性能优化:CPU环境下速度提升秘籍

Rembg抠图性能优化&#xff1a;CPU环境下速度提升秘籍 1. 背景与挑战&#xff1a;Rembg在实际应用中的性能瓶颈 1.1 智能万能抠图 - Rembg Rembg 是近年来广受开发者和设计师青睐的开源图像去背景工具&#xff0c;其核心基于深度学习模型 U-Net&#xff08;U-square Net&…

可能全网唯一!咸鱼流出全新锐龙R5 7535HS主板,ITX小板,双M2+SATA+M2 WIFI,适合一体机和迷你主机DIY装机!

咸鱼总是能够流出各种各样的主板&#xff0c;相比正常&#xff0c;常规尺寸主板&#xff0c;很多小尺寸&#xff0c;ITX规格无疑是板载CPU&#xff0c;这类主板更适合小机箱。但处理器板载不可更换&#xff0c;板U一体的主板的局限就在于此&#xff0c;这在一体机及笔记本主板&…

从2D到3D空间感知|AI单目深度估计-MiDaS镜像全解析

从2D到3D空间感知&#xff5c;AI单目深度估计-MiDaS镜像全解析 &#x1f310; 技术背景&#xff1a;为何我们需要“看懂”三维世界&#xff1f; 在计算机视觉的发展历程中&#xff0c;从2D图像理解3D结构始终是一个核心挑战。传统方法依赖双目立体匹配、激光雷达或多视角几何…

Python圣诞树代码:零基础也能轻松学会

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请创建一个适合Python初学者的圣诞树代码教学示例。要求&#xff1a;1. 从最简单的单层树开始 2. 每步添加一个新功能&#xff08;如树干、装饰品等&#xff09; 3. 每个代码块都有…

WSL实战:在Windows上完美运行Linux开发环境

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个WSL实战项目模板&#xff0c;包含&#xff1a;1. 配置完整的LAMP/MEAN开发环境 2. 设置VS Code远程开发 3. 数据库服务配置&#xff08;MySQL/PostgreSQL&#xff09; 4. …

大模型落地全景指南:从技术实现到商业价值

大模型落地是当前AI领域的核心课题&#xff0c;涉及技术选型、工程实践与商业适配的复杂融合。本文系统拆解微调&#xff08;参数级定制&#xff09;、提示词工程&#xff08;非参数级引导&#xff09;、多模态交互&#xff08;跨模态理解与生成&#xff09;及企业级解决方案&a…

点量云流实时云渲染:如何设置分辨率?三招搞定!

在日常工作中&#xff0c;咱们的同事经常收到客户关于分辨率设置的询问&#xff1a;“怎么设置分辨率&#xff0c;很多用户访问&#xff0c;终端设备不同&#xff0c;怎么设置不同的分辨率&#xff1f;”“云流管理后台设置了分辨率以后&#xff0c;会不会所有终端都是一样的分…

ORA-28547错误图解指南:新手也能轻松解决

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个面向初学者的交互式教程应用&#xff0c;通过可视化流程图展示ORA-28547错误的排查步骤。应用应包含动画演示错误发生场景、图解配置检查点(如监听器状态、TNS条目)、简单…

基于Java开源框架搭建的零代码+可视化编排引擎(附功能清单)

什么是服务编排服务编排是通过图形化的方式表达后端业务逻辑的能力 &#xff0c; 它能够帮助我们通过可视化、 拖拉拽式进行业务逻辑的定义、 实现服务的整合调用、 数据的加工计算等多种场景。JVS逻辑引擎是一款基于可视化拖拽和原子服务编排的逻辑引擎&#xff0c;通过将复杂…

Rembg抠图WebUI部署教程:一键生成透明PNG图片

Rembg抠图WebUI部署教程&#xff1a;一键生成透明PNG图片 1. 引言 1.1 智能万能抠图 - Rembg 在图像处理、电商设计、内容创作等领域&#xff0c;精准的背景去除是一项高频且关键的需求。传统手动抠图耗时费力&#xff0c;而基于AI的自动去背技术正逐步成为主流。其中&#…

对比评测:传统vs智能2258XT量产工具效率差异

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个2258XT量产效率对比测试工具&#xff0c;功能包括&#xff1a;1.自动记录传统量产过程各阶段耗时 2.智能工具操作过程监控 3.生成对比统计图表 4.坏块率等质量指标分析 5.…

Rembg边缘处理:透明物体抠图进阶技巧

Rembg边缘处理&#xff1a;透明物体抠图进阶技巧 1. 引言&#xff1a;智能万能抠图 - Rembg 在图像处理与视觉设计领域&#xff0c;精准去背景是提升内容质量的关键环节。无论是电商产品精修、UI设计中的图标提取&#xff0c;还是AI生成内容的后处理&#xff0c;都需要一种高…

Rembg抠图质量评估:用户满意度调查

Rembg抠图质量评估&#xff1a;用户满意度调查 1. 智能万能抠图 - Rembg 在图像处理与内容创作日益普及的今天&#xff0c;自动去背景技术已成为设计师、电商运营、AI开发者乃至普通用户的刚需。传统手动抠图耗时耗力&#xff0c;而基于深度学习的智能抠图工具则提供了“一键…

1小时搭建软件包依赖分析原型系统

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速开发一个最小化软件包依赖分析原型&#xff0c;要求&#xff1a;1) 基本依赖关系解析 2) 简单冲突检测 3) 基础可视化展示 4) 支持Ubuntu系统 5) 极简命令行界面。使用Python实…

Rembg API开发:构建云端抠图服务

Rembg API开发&#xff1a;构建云端抠图服务 1. 智能万能抠图 - Rembg 在图像处理领域&#xff0c;自动去背景&#xff08;抠图&#xff09;一直是高频且关键的需求。无论是电商商品展示、证件照制作&#xff0c;还是设计素材提取&#xff0c;传统手动抠图耗时耗力&#xff0…