热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【译】数据库B树索引的工作原理

当我们考虑数据库的性能时,首先想到的是索引。在这里,我们将研究数据库索引如何在数据库上工作。请注意,这里的架构细节是参考SQLite2.x数据库架构来描述的。阅读这篇DZone文章

原文链接:https://dzone.com/articles/database-btree-indexing-in-sqlite

作者:Dhanushka Madushan


当我们考虑数据库的性能时,首先想到的是索引。在这里,我们将研究数据库索引如何在数据库上工作。请注意,这里的架构细节是参考 SQLite 2.x 数据库架构来描述的。您可以通过测试找到 SQLite 2.5.0 的后端实现,这与来自 https://github.com/madushadhanushka/simple-sqlite 的这篇文章相关。

阅读这篇 DZone 文章中的整体 SQLite 数据库架构是如何组成的。

什么是 B-tree ?

B-tree 是一种数据结构,它提供排序的数据,并允许按排序顺序进行搜索、顺序访问、附件和删除。 B-tree 非常适合写入大块数据的存储系统。 B 树通过允许具有两个以上子节点的节点来简化二叉搜索树。以下为样本 B 树示例:

企业微信截图_20220624150318.png

B-tree 存储数据,使得每个节点包含按升序排列的键。这些键中的每一个都有对另外两个子节点的两个引用。左侧子节点键小于当前键,右侧子节点键多于当前键。如果单个节点有“n”个键,那么它最多可以有“n+1”个子节点。

为什么在数据库中使用索引?

想象一下,您需要在文件中存储一个数字列表并在该列表中搜索给定的数字。最简单的解决方案是将数据存储在数组中,并在新值出现时附加值。但是如果你需要检查给定的值是否存在于数组中,那么你需要一一搜索所有的数组元素并检查给定的值是否存在。如果你足够幸运,你可以在第一个元素中找到给定的值。在最坏的情况下,该值可能是数组中的最后一个元素。我们可以用渐近符号将这种最坏情况表示为 O(n)。这意味着如果您的数组大小最多为“n”,则您需要执行“n”次搜索才能在数组中找到给定值。

这次你怎么改进?最简单的解决方案是对数组进行排序并使用二进制搜索来查找值。每当您将值插入数组时,它都应该保持顺序。从数组中间选择一个值开始搜索。然后将所选值与搜索值进行比较。如果所选值大于搜索值,则忽略数组的左侧并搜索右侧的值,反之亦然。

3.png

在这里,我们尝试从数组 3、6、8、11、15 和 18 中搜索键 15,它们已经按排序顺序排列。如果您进行正常搜索,则由于元素位于第五个位置,因此需要五个单位的时间进行搜索。但是在二分查找中,它只需要三个查找。

如果我们将此二进制搜索应用于数组中的所有元素,则如下所示。

4.png

看着眼熟?它是一棵二叉树。这是 B 树的最简单形式。对于二叉树,我们可以使用指针而不是将数据保存在排序数组中。在数学上,我们可以证明二叉树的最坏情况搜索时间是 O(log(n))。二叉树的概念可以扩展为更广义的形式,称为 B 树。 B-tree 不是为单个节点使用单个条目,而是为单个节点使用条目数组,并为每个条目引用子节点。以下是每种预先描述的方法的一些时间复杂度比较。

5.png

B+tree是另一种用于存储数据的数据结构,看起来和B-tree几乎一样。 B+tree 的唯一区别是它在叶子节点上存储数据。这意味着所有非叶节点值再次在叶节点中重复。下面是一个示例 B+树。

6.png

13、30、9、11、16 和 38 个非叶值在叶节点中再次重复。你能在叶子节点看到这棵树的特长吗?

是的,叶节点包括所有值,所有记录都按排序顺序排列。 B+tree 的特点是,你可以进行与 B-tree 相同的搜索,此外,如果我们如下放置一个指向每个叶节点的指针,你可以遍历叶节点中的所有值。

企业微信截图_20220624151201.png

如何在数据库中使用索引?

当 B-tree 涉及到数据库索引时,这个数据结构变得有点复杂,不仅有一个键,而且还有一个与键关联的值。该值是对实际数据记录的引用。键和值一起称为有效负载。

假设需要将以下三列表存储在数据库中。

7.png

首先,数据库为每个给定记录创建一个唯一的随机索引(或主键),并将相关行转换为字节流。然后,它将每个键和记录字节流存储在 B+树上。这里,随机索引用作索引的键。密钥和记录字节流统称为有效载荷。生成的 B+树可以表示如下。

企业微信截图_20220624152325.png

在这里你可以看到所有的记录都存储在 B+tree 的叶子节点中,并且索引用作创建 B+tree 的 key。没有记录存储在非叶节点上。每个叶节点都引用了树中的下一条记录。数据库可以通过使用索引或顺序搜索来执行二进制搜索,方法是仅通过叶节点来搜索每个元素。

如果不使用索引,则数据库读取这些记录中的每一个以找到给定的记录。启用索引后,数据库会为表中的每一列创建三个 B 树,如下所示。这里的键是用于索引的 B 树键。索引是对实际数据记录的引用。

10.png

当首先使用索引时,数据库搜索给定的键对应于 B-tree 并在 O(log(n)) 时间内获取索引。然后,它在 O(log(n)) 时间内使用已经找到的索引在 B+tree 中执行另一次搜索并获取记录。

B-tree 和 B+tree 中的每个节点都存储在 Pages 中。页面大小固定。页面具有从一开始的唯一编号。通过使用页码,一个页面可以是对另一个页面的引用。在页面的开头,页面元详细信息,例如最右边的子页号、第一个空闲单元格偏移量和存储的第一个单元格偏移量。数据库中可以有两种类型的页面:



  • 用于索引的页面:这些页面仅存储索引和对另一个页面的引用。



  • 存储记录的页面:这些页面存储实际数据,页面应该是叶子页面。



使用 SQLite B 树索引

创建 B-tree 索引的基本语法如下:

CREATE INDEX index_name ON table_name;

SQLite 中使用了三种索引方法。

1.单列索引

在这里,索引是基于一个表列创建的。只为索引创建一个 Btree。语法如下:

CREATE INDEX index_name ON table_name (column_name);

2.唯一索引

唯一索引不允许为使用索引的列存储重复值。语法可以写成如下:

CREATE UNIQUE INDEX index_name on table_name (column_name);

3.综合索引

这种类型的索引可以有多个索引。对于每个索引列,都存在一个 B-tree。以下是复合索引的语法:

CREATE INDEX index_name on table_name (column1, column2);

结 论

数据库应该有一种有效的方式来存储、读取和修改数据。 B-tree 提供了一种插入和读取数据的有效方法。在实际的 Database 实现中,数据库同时使用 B-tree 和 B+tree 来存储数据。 B-tree 用于索引,B+tree 用于存储实际记录。 B+tree 除了提供二分查找外,还提供顺序查找功能,这使数据库可以更好地控制在数据库中搜索非索引值。



推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
author-avatar
梦回大唐2502907957
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有