SQL进阶理论篇(四):索引的结构原理(B树与B+树)

news2024/11/15 19:27:25

文章目录

  • 简介
  • 如何评价索引的数据结构设计好坏
  • 二叉树的局限性
  • 什么是B树
  • 什么是B+树
  • 总结
  • 参考文献

简介

我们在上一节中说过,索引其实是一种数据结构,那它到底是一种什么样的数据结构呢?本节将简单介绍一下几个问题:

  • 什么样的数据结构更适合作为索引?平衡二叉树是否合适?
  • 什么是B树和B+树,为什么我们常用B+树作为索引的数据结构?

如何评价索引的数据结构设计好坏

由于索引是存放在磁盘上的,所以我们在通过索引来查找某行数据的时候,大量的时间其实是花在了磁盘的IO上。

因此,如果我们能让索引的数据结构尽量减少与磁盘的IO次数,那么就能减少查询所消耗的时间,这样的数据结构就是更好的。

二叉树的局限性

二叉树是一种高效且常见的数据检索方式。其时间复杂度为O(log2N),那么,采用二叉树作为索引的数据结构合适么?

让我们看一下最基础的二叉搜索树,假设需要搜索的数值是key:

  • 如果key大于根节点,则在右子树中进行查找;
  • 如果key小于根节点,则在左子树中进行查找;
  • 如果key等于根节点,那么就是找到了这个节点。

举个例子,(34,22,89,5,23,77,91)创造出来的二叉搜索树为:

在这里插入图片描述

最多只需要经过3次搜索,就能找到指定值。

但是存在特殊的情况,比如说以(5, 22, 23, 34, 77, 89, 91)的顺序创造出来的二分查找树为:

在这里插入图片描述

在这个树里,最多需要经过7次比较之后才能找到指定的节点。

因为第二棵树实际上已经退化成了一张链表,查找数据的时间复杂度变成了O(n)。

当然,如果使用平衡二叉搜索树的话,就可以解决这个问题,因为平衡二叉数在二分搜索树的基础上添加了约束,其约定每个节点的左子树和右子树的高度差不能超过1,即左右子树依然是平衡二叉树。

常见的平衡二叉树有很多种,比如说平衡二叉搜索树、红黑树、数堆、伸展树。平衡二叉搜索树是最早提出的一种平衡二叉树。因此我们一般说的平衡二叉树,其实就是平衡二叉搜索树,搜索时间复杂度就是 O ( l o g 2 n ) O(log_2n) O(log2n)

由于每访问一次节点就要进行一次磁盘IO操作,所以对平衡二叉搜索树来讲,一般会进行 O ( l o g 2 n + 1 ) O(log_2n+1) O(log2n+1)次IO操作。比如说一个5层的平衡二叉树,共31个节点,正常会进行5次IO操作。树的深度越大,意味着IO操作的次数就越多,就越影响整体数据查询的效率。

所以我们可以考虑下,如果将二叉树换成M叉树(M>2),是不是就可以降低树的高度了呢?比如说,同样的31个节点,使用三叉树来存储的话,树深就变成了 l o g 3 ( 31 + 1 ) log_3(31+1) log3(31+1),就是4层。

可以看到,此时树的高度降低了,当数据量足够大的时候,确实比二叉树要好一些。

什么是B树

上一小节中,我们讲到了M叉树(M>2)的表现要优于二叉树。因此一个节点应该允许有M个子节点。

B树就是这么被提出来的。B树,即Balance Tree,就是平衡的多路搜索树,它的高度远小于平衡二叉搜索树的高度。在文件系统和数据库系统中的索引结构经常使用B树来实现

B树的结构如下图:

在这里插入图片描述

可以看到,B树中每个节点最多可以包含M个子节点,而M则称为是B树的阶

同时,每个磁盘块中包括了关键字(如17/35)和子节点的指针(如P1、P2和P3)。指针数是关键字数量 + 1。

对一个100阶的B树来讲,如果有3层的话最多可以存储 ( 99 ∗ 1 + 99 ∗ 10 0 1 + 99 ∗ 10 0 2 ) = 999999 (99*1 + 99*100^1 + 99*100^2)=999999 991+991001+991002=999999,约100w的索引数据。

在存储数据相同的情况下,其高度远远低于二叉树的高度。

简单总结下,一个M阶B树(M>2)的特性:

  • 根节点的孩子节点数为[2, M]
  • 每个中间节点包含n-1个关键字和n个孩子,其中n的取值范围是[ceil(M/2),M]
  • 假设中间节点的关键字为 k 1 , k 2 , . . . . , k n − 1 k_1, k_2,....,k_{n-1} k1,k2,....,kn1,且关键字按照升序排序,即 k i < k i + 1 k_i < k_{i+1} ki<ki+1。此时n-1个关键字相当于是划分出了n个数值范围,因此对应着n个指针,即 P 1 , P 2 , . . . . , P n P_1, P_2,....,P_n P1,P2,....,Pn,其中, P 1 P_1 P1指向关键字小于 K 1 K_1 K1的子节点, P 2 P_2 P2指向关键字属于 ( k 1 , k 2 ) (k_1, k_2) (k1,k2)的节点,以此类推。
  • 所有叶子节点位于同一层。

可以结合上面图来查看刚刚总结的这些特性。

相比平衡二叉树,B树的深度要更低,从而要进行的磁盘IO操作也更少,在数据查询中的效率就显得更高。

虽然M越大,一次读进内存的用来比较的数据就越多,但这个比较的过程是在内存里进行的,时间消耗可以忽略不计

什么是B+树

B+树是对B树的改进,主流的DBMS都支持B+树的索引方式,比如说MySQL。

B+树和B树的差异在哪儿呢?

  • 每个节点内的关键字数量和孩子数量一样。而B树中,孩子数量 = 关键字数量 + 1;
  • 非叶子节点的关键字也会同时出现在子节点里,并且是子节点关键字里的最大或者最小。而B树中,则不会同时出现在子节点中;
  • 非叶子节点仅用于索引,不保存数据记录,所有的数据记录都是放在叶子节点里。而B树中,所有的节点都是可以既保存索引,也保存数据记录。
  • 所有关键字都在叶子节点里出现,每个节点内部所有关键字按照大小从小到大顺序排列,所有叶子节点构成一个有序链表。

比如说下面这张图,就是一棵B+树:

在这里插入图片描述

比如说,想查找关键字16,就会自顶向下逐层进行查找,先后访问磁盘块1、磁盘块2、磁盘块7。三次IO操作即可。

在IO的次数上,B+ 树看起来似乎跟B树差不多,那么B+树到底好在哪儿呢?

这个要看B+树和B树的根本差异:B+树的中间节点并不直接存储数据

这样有什么好处呢?

首先,B+树查询效率更加稳定。B+树每次只有访问到叶子节点后才能取出数据,而B树中,由于非叶子节点也可以存储数据,这就造成了查询效率不稳定的情况,有时候需要访问到叶子节点才能找到数据,有时候走一半到非叶子节点就可以找到数据。时间不好量化。

其次,B+树查询效率更高。通常B+树比B树更矮胖(非叶子节点只存放索引,因此一个节点可以放更多关键字,从而减少深度),所需的磁盘IO就更少。同样的磁盘页大小,B+树可以存储更多的节点关键字。

在做区间查询的时候,B+树的效率同样比B树高。因为B+树里,所有的关键字都出现在叶子节点上,并通过有序链表进行了链接,非常适合寻找范围数据。而B树则需要通过中序遍历扫一遍才能完成范围数据的查找,效率要低很多。

总结

索引在使用时,时间的消耗主要是两部分带来的,一是读取磁盘块来取出里面保存的索引值数据,二是比较索引值数据。不过比较的工作是在内存中进行的,速度很快,所以这部分时间其实可以忽略不计。

因此,制约索引使用速度的唯一因素,就是与磁盘块的IO。只要能减少这块的IO,就能减少索引在使用时的时间消耗,从而提升整个查询的效率。

构造索引的时候,我们更倾向于采用矮胖的数据结构,因此平衡二叉树的结构被果断舍弃了。

B树和B+树都可以作为索引的数据结构,在MySQL中采用的是B+树,其查询性能更加稳定,在磁盘页大小相同的情况下,树的构造更加矮胖,所需要的IO次数更少,也更适合进行关键字的范围查找。

参考文献

  1. 24丨索引的原理:我们为什么用B+树来做索引?

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

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

相关文章

【开源Mongdb驱动】SpringBoot+Mybatis+Mongdb融合使用教程

#【开源Mongdb驱动】SpringBootMybatisMongdb无缝融合使用教程 介绍 本文介绍一款基于JAVA开源的mongodb jdbc驱动为基础的无缝与springbootmybatis融合使用案例 mongodb JDBC 使用案例 https://blog.csdn.net/gongbing798930123/article/details/135002530 《基于开源的JA…

鸿蒙原生应用/元服务开发-Stage模型能力接口(四)

一、说明 AbilityStage是HAP的运行时类。AbilityStage类提供在HAP加载的时候&#xff0c;通知开发者&#xff0c;可以在此进行该HAP的初始化&#xff08;如资源预加载&#xff0c;线程创建等&#xff09;能力。 本模块首批接口从API version 9 开始支持。后续版本的新增接口&…

Unity Web 浏览器-3D WebView中有关于CanvasWebViewPrefab

一、CanvasWebViewPrefab默认设置 这个是在2_CanvasWebViewDemo示例场景文件中可以可以查看得到&#xff0c;可以看出CanvasWebViewPrefab的默认配置如下。 二、Web 浏览器网页和Unity内置UI的渲染顺序 1、如果你勾选了以下这个Native 2D Mode选项的话&#xff0c;那么Unit…

RocketMQ Connect详解

一、概览 RocketMQ Connect是RocketMQ数据集成重要组件&#xff0c;可将各种系统中的数据通过高效&#xff0c;可靠&#xff0c;流的方式&#xff0c;流入流出到RocketMQ&#xff0c;它是独立于RocketMQ的&#xff0c;一个单独的分布式、可扩展、可容错系统&#xff0c; 它具备…

现代雷达车载应用——第2章 汽车雷达系统原理 2.1节 基本雷达功能

经典著作&#xff0c;值得一读&#xff0c;英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.1 基本雷达功能 雷达系统通过天线或天线阵列向空间辐射电磁能量。辐射的电磁能量“照亮”周围的目标。“被照亮”的目标拦截一些辐射能量&#xff0…

LeetCode(59)反转链表 II【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 反转链表 II 1.题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&am…

东北大学Python

目前金属矿开采&#xff0c;爆破还是主要的破岩方式&#xff0c;为了保证巷道采场的安全&#xff0c;需要对爆破震动进行监测&#xff0c;获取的监测数据如附件&#xff0c;第1列数据为震动的序号&#xff0c;第2、3、4列为x,y,z三个方向的震动速度&#xff0c;往往由于各种因素…

module ‘tensorflow‘ has no attribute XXX 报错解决

问题描述&#xff1a; 粘了别人的tensorflow项目&#xff0c;运行总是报错module ‘tensorflow’ has no attribute什么什么 问题解决&#xff1a; 导入tensorflow的代码如下 import tensorflow as tf此时&#xff0c;某个某块报错&#xff0c;比如下面这个 那么就直接把tf.…

100:ReconFusion: 3D Reconstruction with Diffusion Priors

简介 官网 少样本重建必然导致nerf失败&#xff0c;论文提出使用diffusion模型来解决这一问题。从上图不难看出&#xff0c;论文一步步提升视角数量&#xff0c;逐步与Zip-NeRF对比。 实现流程 Diffusion Model for Novel View Synthesis 给定一组输入图像 x o b s { x i…

Tomcat部署(图片和HTML等)静态资源时遇到的问题

文章目录 Tomcat部署静态资源问题图中HTML代码启动Tomcat后先确认Tomcat是否启动成功 Tomcat部署静态资源问题 今天&#xff0c;有人突然跟我提到&#xff0c;使用nginx部署静态资源&#xff0c;如图片。可以直接通过url地址访问&#xff0c;为什么他的Tomcat不能通过这样的方…

卧槽!jmeter 竟然这么牛逼,压测爽歪歪~

# Http请求模拟 1、新建线程组 操作&#xff1a;鼠标右键测试计划 -> 添加 -> Threads(Users) -> 线程组 -> 修改测试计划名称 新建线程组 2、添加取样器HTTP请求 操作&#xff1a;鼠标右键线程组 -> 添加 -> Sampler -> HTTP请求 -> 填写请求参数 添…

Mybatis的foreach标签的使用以及参数的含义

Mybatis的foreach标签的使用以及参数的含义 语法格式&#xff1a; 属性说明&#xff1a; collection属性的注意点&#xff1a;

LabVIEW在高铁温度与振动监测中的应用

​LabVIEW在高铁温度与振动监测中的应用 高速铁路的可靠性和安全性是现代铁路运输系统设计和运营的重中之重。LabVIEW软件作为一个多功能、可扩展的图形编程环境&#xff0c;提供了一个理想的平台&#xff0c;用于开发高铁监测系统&#xff0c;不仅监测实时数据&#xff0c;也…

LangChain(0.0.340)官方文档九:Retrieval——Text embedding models、Vector stores、Indexing

LangChain官网、LangChain官方文档 、langchain Github、langchain API文档、llm-universe 文章目录 一、Text embedding models1.1 Embeddings类1.2 OpenAI1.3 Sentence Transformers on Hugging Face1.4 CacheBackedEmbeddings1.4.1 简介1.4.2 与Vector Store一起使用1.4.3 内…

小程序 -网络请求post/get

1.1网络请求的概念(post和get) 1.2步骤 1.3 应用函数 js里面写&#xff0c;用bindtap绑在控件上&#xff0c;就不讲了 实例代码&#xff1a; //发起get数据请求get_info(){wx.request({url:https://www.escook.cn/api/get,//请求的接口地址,必须基于https协议//请求的方式met…

Flutter 打包 iOS 苹果 IPA 应用有哪些优势?如何实现?

经常和移动应用开发相关的话题打交道的伙伴们都知道。在开发移动应用时&#xff0c;选择合适的打包方式对于应用的发布和分发至关重要。在今天这篇文章中&#xff0c;我将和大家聊聊 Flutter 打包 iOS 苹果 IPA 应用的优势&#xff0c;并分享一些使用 Flutter 打包 ios 苹果 ip…

克隆图[中等]

一、题目 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。图中的每个节点都包含它的值val&#xff08;int&#xff09;和其邻居的列表list[Node]。 class Node {public int val;public List<Node> neighbors; }测试…

【WinForm.NET开发】使用 Padding、Margin 和 AutoSize 属性布置控件

本文内容 创建项目设置控件的边距设置控件的填充自动调整控件大小AutoSize 和 AutoSizeMode 属性后续步骤 在窗体上精确地放置控件对于许多应用程序而言是高优先级。 Visual Studio 中的 Windows 窗体设计器提供了许多布局工具来实现此目的。 其中三个最重要的是 Margin、Pad…

孩子都能学会的FPGA:第三十一课——用FPGA实现SPI主机发送数据

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

保障网络安全:了解威胁检测和风险评分的重要性

在当今数字时代&#xff0c;网络安全问题变得愈发突出&#xff0c;而及时发现和迅速应对潜在威胁成为保障组织信息安全的首要任务。令人震惊的是&#xff0c;根据2023年的数据&#xff0c;平均而言&#xff0c;检测到一次网络入侵的时间竟然长达207天。这引起了对安全策略和技术…