【每日八股】MySQL篇(三):索引(上)
目录
- MySQL 为什么使用 B+ 树来做索引,它的优势是什么?
- 特性和定义
- B+ 树和 B 树的对比
- 拓展:既然 B+ 树相较于 B 树优势如此之大,为什么 nosql 的 MongoDB 底层仍采用 B 树而不是 B+ 树?
- 使用 B+ 树做索引的优势
- 补充:为什么说 B+ 树的插入和删除效率高?B+ 树的冗余结点是如何形成的?它们的作用是什么?冗余结点是如何帮助提高插入和删除效率的?冗余结点指的是叶子节点冗余还是用做索引的非叶子节点冗余?
- 为什么说 B+ 树的插入和删除效率高?结构特性带来的效率优势
- 冗余节点的形成与作用
- 冗余结点提升效率的原理
- 冗余结点指的是叶子节点冗余还是用做索引的非叶子节点冗余?冗余结点的本质
- 与其它数据结构的对比
- 索引有哪些种?
- 单值索引
- 唯一索引
- 主键索引
- 复合索引
- 前缀索引
- 什么是最左匹配原则?
- 拓展:最左匹配原则是数据库索引设计的核心概念之一,主要针对联合查询
- 索引区分度?
- 联合索引如何进行排序?
MySQL 为什么使用 B+ 树来做索引,它的优势是什么?
特性和定义
B+ Tree 是一种多叉树,叶子节点才存放具体的数据而非叶子节点仅存放索引,每个结点当中的数据是按主键顺序存放的。在叶子节点中,包括了所有的索引值信息,并且每一个叶子节点都指向下一个叶子节点,形成一个链表(因此 B+ 树支持范围查询)。B+ Tree 存储千万级别的数据只需要 3 ~ 4 层高度就可以满足(加入一个非叶子结点存储 1000 个索引,那么三层树高的情况下可以存储 100 0 3 = 1000000000 1000^3 = 1000000000 10003=1000000000十亿条数据),千万级的表查询最多只需要 3 ~ 4 次磁盘 I/O。
B+ 树和 B 树的对比
-
数据存储分布:
B 树:所有结点均存储数据(键值对);
B+ 树:仅叶子节点存储完整数据,内部节点仅做索引(键 + 指针); -
叶子节点结构:
B 树:独立叶子节点;
B+ 树:叶子节点通过双向链表串联,形成有序链表结构; -
查询性能对比:
B 树和 B+ 树的单点查询平均时间复杂度相当,均为 O ( log d N ) O(\log_d{N}) O(logdN);
在进行范围查询时,B+ 树通过链表直接进行顺序查询,而 B 树则需要中序遍历,效率差 10 倍。 -
空间利用率:
B+ 树内部可以存储更多的键值,树高普遍比 B 树低 2 层。 -
插入删除操作:
B+ 树数据变更仅影响叶子节点,而 B 树可能引发连锁节点的分裂与合并; -
典型应用场景:
B 树:MongoDB(文档型数据库)、文件系统;
B+ 树:MySQL(InnoDB)、Oracle、PostgreSQL 等关系型数据库; -
工程实践差异:
B+ 树叶子节点存储密度可达 70%,而 B 树通常为 50% ~ 60%;
在处理百万级数据时,B+ 树比 B 树减少 30% ~ 50% 的磁盘 I/O 次数(得益于 B+ 树的高扇出与低树高特性);
在进行范围查询时,B+ 树比 B 树的性能高 5 ~ 10 倍(得益于 B+ 树叶子节点之间的顺序连接特性)。
拓展:既然 B+ 树相较于 B 树优势如此之大,为什么 nosql 的 MongoDB 底层仍采用 B 树而不是 B+ 树?
B+ 树在关系型数据库(如 MySQL)中表现卓越,因其擅长范围查询和排序;而 MongoDB 作为文档数据库,优先优化点查询和文档快速获取,B 树的结构特性更契合其设计目标。
使用 B+ 树做索引的优势
- 单点查询:B 树进行单个索引查询时,最快可以在 O ( 1 ) O(1) O(1)的时间代价内完成(因为 B 树当中的结点,包括非叶子节点,既存储索引又存储数据)。从平均时间代价上来看,它比 B+ 树更快。但是 B 树的查询波动比较大,原因同样是每个节点既存储索引又存储数据,所以有时候访问到非叶子节点即可找到索引,有时候需要访问到叶子节点才能找到索引。B+ 树的非叶子节点不存放实际的记录数据,而只存放索引,在数据量相同的情况下,B+ 树的非叶子节点可以存放更多的索引,查询底层结点的 I/O 更少,因此 B+ 树在做单点查询时更加稳定。
- 插入和删除效率:B+ 树含有大量的冗余结点,删除一个节点时,可以直接从叶子结点删除,甚至可以不动非叶子节点,删除非常快。B+ 树的插入也是一样,有冗余结点,插入可能存在结点的分裂(如果节点饱和),但是最多只涉及树的一条路径。B 树没有冗余结点,删除节点非常复杂,可能涉及复杂的树的变形。
- 范围查询:B+ 树的所有叶子节点直接通过双向链表连接,而 B 树没有将叶子节点通过链表串联,因此 B 树只能通过树的遍历来完成范围查询,其范围查询的效率不如 B+ 树。B+ 树的插入删除效率非常高,当面对存在大量的范围检索的场景时,适合使用 B+ 树,比如数据库;而对于存在大量单个索引查询的场景,可以考虑 B 树,比如 nosql 的 MongoDB。
补充:为什么说 B+ 树的插入和删除效率高?B+ 树的冗余结点是如何形成的?它们的作用是什么?冗余结点是如何帮助提高插入和删除效率的?冗余结点指的是叶子节点冗余还是用做索引的非叶子节点冗余?
为什么说 B+ 树的插入和删除效率高?结构特性带来的效率优势
- 多路平衡特性:每个结点可存储大量键值(高扇出),树高通常维持在 3 ~ 4 层,磁盘 I/O 次数更少;
- 顺序访问优化:叶子节点之间形成有序链表(InnoDB 在实现上使用双向链表),范围查询效率极高;
- 写操作局部性:插入/删除只需要修改局部节点(具体来说,指的就是叶子节点),多数情况下不会引发连锁结构调整。
冗余节点的形成与作用
- 冗余节点类型:主要存在于非叶子节点(即索引节点);
- 形成机制:插入时结点分裂会产生临时性父节点键值冗余,删除节点时合并会暂时保留未及时清理的索引键,批量操作时会延迟维护产生的中间状态;
- 作用:缓冲结构调整压力,避免频繁的节点分裂/合并,允许临时超出结点容量限制,为并发操作提供版本控制的可能性。
冗余结点提升效率的原理
- 延迟维护:非叶子节点的冗余键允许暂时不立即处理结构变更;
- 批量处理:多个操作累积后,一次性处理冗余,摊平维护成本;
- 概率优化:利用节点填充因子(如 70% 阈值)预留空间缓冲突发操作。
冗余结点指的是叶子节点冗余还是用做索引的非叶子节点冗余?冗余结点的本质
冗余结点是 B+ 树用空间换时间的典型设计,通过允许非叶子节点存在临时性的冗余键值,换取更平缓的结构维护代价。叶子节点由于需要保证数据的有序性,冗余主要表现为预留空间而非键值重复。
与其它数据结构的对比
- B+ 树对比 B 树:B+ 树只在叶子节点存储数据,而 B 树的非叶子节点也存储数据。因此 B+ 树的单个结点数据量更小(在数据量相同的前提下,B+ 树可以存储更多的索引),在相同的磁盘 I/O 次数下,B+ 树可以查询更多的结点。B+ 树的叶子节点采用双向链表连接(具体来说,MySQL 的 InnoDB 在实现细节上是采用双向链表的。早期 MySQL 的 MyISAM 引擎使用单向链表,InnoDB 自 MySQL 5.5 称为默认引擎后,叶子节点之间的双向链表连接称为标准实现),适合 MySQL 中常见的基于范围的查询,而 B 树做不到这一点,因此它更适用于单点查询。
- B+ 树对比二叉树:对于有 N 个叶子节点的 B+ 树,其搜索复杂度为 O ( log d N ) O(\log_d{N}) O(logdN),其中 d 表示结点允许的最大子节点个数。实际应用中,d 值大于 100,即使数据达到千万级,B+ Tree 的高度依然维持在 3 ~ 4 层,一次查询只需要 3 ~ 4 次磁盘 I/O 就能查到。二叉树每个父节点的儿子结点个数为 2 个,意味着其搜索复杂度为 P ( log N ) P(\log{N}) P(logN),二叉树搜索到目标数据需要的磁盘 I/O 数更多。
- B+ 树对比哈希:哈希在做等值查询时效率较高,搜索复杂度为 O ( 1 ) O(1) O(1),但是 Hash 不适合做范围查询。
索引有哪些种?
单值索引
单值索引即一个索引只包含单个列,一个表可以有多个单列索引。
- 建表时:加上
key(列名)指定; - 单独创建:
create index 索引吗 on 表名(列名); - 单独创建:
alter table 表名 add index 索引名(列名);
唯一索引
唯一索引中,索引列的值必须唯一,但允许有 null 且 null 可以多次出现。
- 建表时:加上
unique(列名)指定; - 单独创建:
create unique index idx 表名(列名) on 表名(列名); - 单独创建:
alter table 表名 add unique 索引名(列名);
主键索引
设定为主键后,数据库会自动建立索引,InnoDB 为聚簇索引,值必须唯一且不能为 null。
- 建表时:加上
primary key(列名)指定;
复合索引
复合索引即一个索引包含多个列。
- 建表时:加上
key(列名列表)指定; - 单独创建:
create index 索引名 on 表名(列名列表); - 单独创建,
alter table 表名 add index 索引名(列名列表);
前缀索引
对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引,前缀索引可以建立在字段类型为 char、 varchar、binary、varbinary 的列上。使用前缀索引的目的是为了减少索引占用的存储空间,提升查询效率。
- 单独创建:
alter table 表名 add 索引名(column_name(索引长度))。
什么是最左匹配原则?
使用联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。使用联合索引进行查询的时候,如果不遵循最左匹配原则,联合索引会失效。
拓展:最左匹配原则是数据库索引设计的核心概念之一,主要针对联合查询
最左匹配原则规定了在使用联合索引时,查询条件必须从索引定义的最左侧列开始,不能跳过中间的列,这样才能有效地利用索引进行快速检索。
联合索引按照定义时的列顺序构建 B+ 树结构,例如索引(a, b, c),数据先按a排,a相同再按b排,b相同按c排。
联合索引的生效条件是,查询必须包含最左列,条件列需要连续无跳跃。若某列使用范围查询,则其右侧的列无法继续使用索引,比如WHERE a=1 AND b>10 AND c=2,仅a和b有效,c需回表过滤。
案例:
WHERE a=1 AND b>2 AND c=3 -- ✅ 使用a、b(c因b范围查询失效)
WHERE b=2 -- ❌ 缺少最左列a
WHERE a=1 AND c=3 -- ❌ 跳过b,仅用a(c无法走索引)
WHERE a>1 AND b=2 -- ❌ a范围查询后,b无法走索引(失效原因:当a使用范围查询时,b的等值条件无法有效利用索引,数据库只能使用a>1的索引范围扫描,此时b=2的记录在索引中是离散分布的)
索引区分度?
查询优化器在发现某个值出现在表的数据行中的百分比(惯用的百分比界限为 30%)很高时,会忽略索引,进行全表扫描。
联合索引如何进行排序?
以(a, b, c)为例,第一优先级:按 a 列值升序排序;第二优先级:a 相同则按 b 列值升序排序;第三优先级:a 和 b 都相同按 c 值升序排序。
排序特性:
- 局部有序性:每个 a 值的范围内,b 是有序的;每个 a, b 组合内,c 是有序的。
- 跨级断点:a 改变时,b 和 c 的排序重新开始。
对查询的影响:
- 范围查询会破坏后续列的排序优势(如a>1时,b的排列不再全局有序);
- 等值查询能保持后续列的排序(如a=1时,b仍保持升序排列)
相关文章:
【每日八股】MySQL篇(三):索引(上)
目录 MySQL 为什么使用 B 树来做索引,它的优势是什么?特性和定义B 树和 B 树的对比拓展:既然 B 树相较于 B 树优势如此之大,为什么 nosql 的 MongoDB 底层仍采用 B 树而不是 B 树? 使用 B 树做索引的优势补充ÿ…...
在Pycharm中将ui文件修改为py文件
在Pycharm中将ui文件修改为py文件 有些时候,我们需要把QTDesigner生成的.ui文件修改为.py文件 在一些教程中,通常使用cmd打开终端修改,或者是有一些人写了一些脚本来修改 这里我们可以使用pycharm来快速的修改 首先,我们在pyc…...
看视频学习方法总结
以下是提高教学视频吸收率的系统性方法,结合认知科学原理和实际学习场景,帮助您最大化学习效果: 一、观看前的黄金准备阶段 60秒快速扫描法 用1分钟快速浏览视频目录、章节标题和简介,建立知识框架。荷兰伊拉斯姆斯大学实验表明&…...
Matlab 大量接单
分享一个matlab接私活、兼职的平台 1、技术方向满足任一即可 2、技术要求 3、最后 技术方向满足即可 MATLAB:熟练掌握MATLAB编程语言,能够使用MATLAB进行数据处理、机器学习和深度学习等相关工作。 机器学习、深度学习、强化学习、仿真、复现、算法、…...
《深度剖析:生成对抗网络中生成器与判别器的高效协作之道》
在人工智能的前沿领域,生成对抗网络(GAN)以其独特的对抗学习机制,为数据生成和处理带来了革命性的变革。生成器与判别器作为GAN的核心组件,它们之间的协作效率直接决定了GAN在图像生成、数据增强、风格迁移等众多应用中…...
Android6到Android15版本新增的功能和api
Android6到Android15版本新增的功能和api 文章目录 Android6到Android15版本新增的功能和api一、前言二、Android6 后的版本迭代1、Android 6.0(Marshmallow,API 级别 23)新增功能重要 API 2、Android 7.0(Nougat,API …...
【现代Web布局与动画技术:卡片组件实战分享】
📱 现代Web布局与动画技术:卡片组件实战分享 🚀 引言 🌟 在过去的开发过程中,我们共同实现了一个功能丰富的卡片组件,它不仅美观,还具有交互性和响应式设计。这篇文章将分享这个组件背后的技术…...
计算机网络之传输层(传输层提供的服务)
一、可靠的数据传输 传输层提供可靠的数据传输服务,确保数据在传输过程中不丢失、不重复、不乱序,并且能够被正确接收。这通常通过面向连接的协议(如TCP)来实现,TCP通过确认、重传、序号等机制来保证数据传输的可靠性…...
FPGA开发,使用Deepseek V3还是R1(1):应用场景
以下都是Deepseek生成的答案 FPGA开发,使用Deepseek V3还是R1(1):应用场景 FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别 FPGA开发,使用Deepseek V3还是R1&#x…...
哈希表和STL —— unorderde_set/unordered_map【复习笔记】
1. 哈希表的相关概念 1.1 哈希表的定义 哈希表,又称为散列表,是根据关键字直接进行访问的数据结构。 它通过一个哈希函数(Hash Function),建立了一种关键字和存储地址间的直接映射关系,将每个关键字映射…...
计算机毕业设计SpringBoot+Vue.js体育馆使用预约平台(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
42 session反序列化漏洞
参考资料:3. php反序列化从入门到放弃(入门篇) - bmjoker - 博客园 session文件上传漏洞利用原理 当在php.ini中设置session.upload_progress.enabled On的时候,PHP将能够跟踪上传单个文件的上传进度。当上传正在进行时,以及在将与session…...
【Jenkins】个人向-Jenkinsfile如何写
官方参考:https://www.jenkins.io/doc/book/pipeline/syntax/ Pipeline Utility Steps 插件:https://birdbook.com.cn/ops/ci/jenkins/plugins/pipeline%20utility%20steps.html 常用环境变量 含义表达式备注params,传入参数传入参数params…...
staruml绘制时序图和用例图
文章目录 1.文章介绍2.绘制用例图3.绘制时序图 1.文章介绍 之前,我们初步介绍了这个staruml软件的安装和如何使用这个软件对于uml类图进行绘制,当时我们是绘制了这个user类,实现了相关的接口,表示他们之间的关系,在今…...
问题修复-后端返给前端的时间展示错误
问题现象: 后端给前端返回的时间展示有问题。 需要按照yyyy-MM-dd HH:mm:ss 的形式展示 两种办法: 第一种 在实体类的属性上添加JsonFormat注解 第二种(建议使用) 扩展mvc框架中的消息转换器 代码: 因为配置类继…...
Rust配置开发环境+服务器实战
https://www.cnblogs.com/skzxc/p/12129353.html 默认已经安装好MSVC。 官网https://www.rust-lang.org/zh-CN/learn/get-started安装Rust安装器,选择winodwsx64版本 运行安装,将文件夹移动到D盘,安装后,文件夹在C:\Users\xxx下…...
使用DeepSeek+KIMI生成高质量PPT
一、使用DeepSeek DeepSeek官网:DeepSeek 点击“开始对话”,进入交互页面。 在上图中,输入问题,即可获取AI生成的结果。 基础模型(V3):通用模型(2024.12),高…...
虚拟机如何设置ip
在虚拟机中设置IP地址的具体步骤会因虚拟机软件(如VMware、VirtualBox等)和操作系统(如Windows、Linux等)的不同而有所差异。以下是几种常见虚拟机软件和操作系统的IP设置方法。 --- 一、VMware中的IP设置 1.Windows虚拟机 1. 打…...
蓝桥杯 路径之谜
路径之谜 题目描述 小明冒充 XX 星球的骑士,进入了一个奇怪的城堡。 城堡里边什么都没有,只有方形石头铺成的地面。 假设城堡地面是 nnnn 个方格。如下图所示。 按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走…...
Git操作指南:分支合并、回退及其他重要操作
在软件开发的协作过程中,Git 作为一款强大的版本控制系统,能帮助开发者高效管理代码的各个版本和分支。本文将详细介绍 Git 中常见的分支合并、取消本地修改、回退操作等,并提供通俗易懂的解释和步骤指南。 一、分支合并 分支合并是 Git 工…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
