浅析存储引擎(3)-B-tree

2023-10-27

 

浅析日志结构的存储引擎(1)-bitcask
浅析日志结构的存储引擎(2)-SSTable和LSM-Tree

前面两篇文章介绍了比较好理解的日志结构引擎LSM-Tree,但它们不是最常见的索引类型。目前最广泛使用的索引结构是B-tree。B-tree维护着按key排序的key-value对,这样可以实现高效的key-value查找和区间查询。

一、B-tree的存储

前面的文章提到,日志结构存储引擎将数据库分解为可变大小的段,并且始终按顺序写入段(追加写)。而B-tree将数据库分解成固定大小的块和页,通常是PAGESIZE大小4KB(也可能更大),页是读/写的最小单元,这种设计也符合磁盘的读取规则。

以mysql为例,我们都知道InnoDB的存储数据格式是按主键排序的(MyISAM和InnoDB的区别),数据都存储在最底层叶子节点。某一页被指定为B-Tree的根,如下图:

假设我们需要查找key=251,需要沿着200-300的区间,最后找到一个包含单个key=251的父页,再从这个父页中找到存储了key=251的数据页(或者块)的偏移量,从磁盘中读取数据。

假设每层树维护500个叶子节点,那么四级树就可以存储500的4次方*4KB=256TB的数据,查询非常高效。

二、如何解决数据更新的问题?

LSM-Tree的数据更新是追加更新文件(最终删除过时的数据)。

和LSM-Tree不一样,B-Tree-底层的基本写操作是使用新数据覆盖磁盘上的旧页。可以理解为磁头先移动到正确位置,然后旋转盘面,最后用新的数据覆盖相应的扇区(SSD的覆盖写更加复杂,需要擦写更大的数据块,可能会产生写放大)。也就是说当数据被覆盖时,索引上对该页的引用并不需要改变。

当然也有例外情况

情况1:假设新覆盖的数据大小超过了原来的页大小,就需要分裂页,同时覆盖其父页,以更新对两个子页的引用(页的偏移量)。

情况2:假设只增加新key,当找到包含其范围的页时,假设页没有足够的空间来容纳新key,那么就需要分裂为两个半满的页,并且父页也需要更新对子页的引用。如下图,插入新key"334":

风险:上述的情况1和情况2在需要更新子页的同时,还需要更新父页对子页的引用,由于至少需要两次磁盘操作,很有可能更新完子页数据库就崩溃了,来不及更新父页,产生了孤儿页。常见B-tree的实现在磁盘上增加重做日志,这是一个仅支持追加修改的文件,作用类似前面讲到的SSTable的日志文件,用于崩溃时恢复数据。

 

参考《数据密集型应用系统设计》

原文出自:https://blog.csdn.net/daiyudong2020/article/details/104717904

end

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅析存储引擎(3)-B-tree 的相关文章

  • 使用 PHP 代码和 HTML 表单将 Excel (.csv) 导入 MySQL

    我知道还有其他类似的帖子 但每个人都建议直接在 PHPMyAdmin 中将其导入 MySQL 这工作完美 但我需要通过 HTML 表单导入 PHP 到 MySQL 我想要一个收集文件的 HTML 表单 然后将该文件传递给 PHP 脚本 我想
  • 使用 mysql2 gem 获取最后插入的 id

    我有这样的代码 require mysql2 db query insert into clients Name values client 我可以通过 1 个查询返回最后插入的 ID 吗 您可以使用last id客户端实例的方法 clie
  • PDO fetch() 失败时会抛出异常吗?

    有没有方法PDO语句 fetch http php net manual en pdostatement fetch php如果 PDO 错误报告系统设置为抛出异常 则在失败时抛出异常 例如 如果我设置 PDO ATTR ERRMODE g
  • MySQL 触发器和 SUM()

    我有两张桌子 学生桌和家庭桌 在学生中 我有列 st venue 和total venue 家里我有收入 Total Revenue 是学生 st 收入与家庭收入之和 其中 family id student student id stud
  • Spark SQL/Hive 查询通过 Join 永远持续下去

    所以我正在做一些应该很简单的事情 但显然它不在 Spark SQL 中 如果我在 MySQL 中运行以下查询 查询将在不到一秒的时间内完成 SELECT ua address id FROM user u inner join user a
  • 选择MySql表数据放入数组中

    我尝试从 mysql 捕获数据并将它们全部放入数组中 认为 users table id name code 1 gorge 2132 2 flix ksd02 3 jasmen skaod2 sql mysql query select
  • 在 MySQL 中分割逗号分隔值

    我正在尝试将字符串中以逗号分隔的 值拆分为多列 样本数据 COL1 COL2 COL3 000002 000003 000042 09 31 51 007 004 007 预期输出 Pno Cno Sno 000002 09 007 000
  • 让 Prometheus 发送 SQL 查询

    我正在尝试使用普罗米修斯 https prometheus io 监视我的 MySQL 数据库 但似乎找不到添加 SQL 查询的区域 例如 我想运行一个返回值的 SQL 查询 然后将该值添加到图表中 发送警报 有没有办法让 Promethe
  • SQLSTATE[HY000] [2002] 资源暂时不可用 - mysql - innodb 和 pdo

    在我的错误日志中得到大量结果 如下所列 数据库中的所有表都是 innodb 并且就与这些表的任何交互而言 一切都是带有准备好的语句的 pdo 正如我所说 所有错误几乎与下面列出的错误相同 但发生在几个不同的页面上 无论页面如何 错误行始终指
  • 在 MySQL 数据库上使用版本控制 (Git)

    我是一名 WordPress 设计师 开发人员 越来越多地使用版本控制 特别是 Git 尽管我确实在某些项目中使用 SVN 我目前正在使用 Beanstalk 作为我的远程仓库 将所有 WordPress 文件添加到我的存储库中是没有问题的
  • 将 mysql LONGTEXT 值转换为 VARCHAR 值?

    我有一个在用户 Facebook 墙上发布的功能 我发送到 facebook 的一件事是我从设置为 LONGTEXT 的 mysql 表中获取的一些文本 如果我将表设置为 LONGTEXT 则文本不会发送到 facebook 但如果我将表设
  • 在 MySQL 中创建布尔列并将 false 作为默认值?

    我想在 MySQL 中创建一个表boolean默认值为的列false 但它默认接受 NULL 你必须指定0 意思是假 或1 意思是 true 作为默认值 这是一个例子 create table mytable mybool boolean
  • MYSql 前 10 名及其他总计

    我的查询运行良好 但我只需要前 10 个供应商 然后我需要将所有剩余的总计放在 所有其他 行中 如果没有单独的查询 我该如何做到这一点LIMIT 10 18446744073709551615 SELECT VENDOR fullname
  • 消除 JPA 标准中子查询产生的冗余连接

    我只需要使用 JPA 标准执行以下 MySQL 查询 获取状态列表 来自state table 基于给定的国家名称 在country SELECT state id state name country id FROM state tabl
  • 将此 MySQL 查询转换为 PyGreSQL

    我正在开发一个 Ruby 应用程序 它使用 mysql 函数 XOR 和 BIT COUNT 不过 我现在需要在运行 PyGreSQL 的 Heroku 上运行该应用程序 我找不到任何可以帮助我的 PyGreSQL 文档 那么任何人都可以翻
  • 如何编写 bash 函数来包装另一个命令?

    我正在尝试编写一个函数包装器mysql command If my cnf存在于 pwd 中 我想自动附加 defaults file my cnf到命令 这就是我正在尝试的 function mysql if e my cnf then
  • 有没有办法只安装mysql客户端(Linux)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有不需要安装整个mysql db安装包的Linux mysql命令行工具 我想做的是从服务器 1 应用程序服务器 执行将在服务器 2
  • MySQL 和 MariaDB 数据库有什么区别?

    我已经使用 XAMPP 很长时间了 很惊讶 XAMPP 已经从 MySQL 切换到了 MariaDB https www apachefriends org index html https www apachefriends org in
  • 如何告诉node.js mysql没有在默认端口上运行?

    我遇到了与此人类似的问题 连接 ECONNREFUSED 节点 js sql https stackoverflow com questions 8825342 connect econnrefused node js sql 我正在尝试将
  • 安装后步骤未成功完成 MySQL Mac OS Sierra

    pyEnv Anants MacBook Pro litibackend anantchandra brew postinstall mysql gt Postinstalling mysql gt usr local Cellar mys

随机推荐

  • 【CSS】css的background属性用法详解,background常用缩写形式

    background是一个简写属性 可以在一个声明中设置背景颜色 背景位置 背景大小 背景平铺方式 背景图片等样式 语法background 颜色 图片 位置 大小 平铺方式 bg origin 绘制区域 bg attachment bac
  • 区块链开源项目

    bitcoin stars gt 100 forks gt 50 bitcoin OR wallet stars gt 100 forks gt 50 in file extension md 我们使用github的搜索功能 并选择fork
  • jmeter版本不支持的 jdk版本 解决办法

    在win7上安装了apache jmeter 2 11和jdk1 8 0 20 配置成功后 点击jmeter bat报错 截图如下 在网上搜索说是要注释掉set DUMP XX HeapDumpOnOutOfMemoryError 可是注释
  • 为什么你的pycharm打开时很卡,今天来教你解决方案

    相信很多刚开始使用pycharm不太熟练的小伙伴 每天一开机打开pycharm总是卡半天 不知道的还以为是电脑卡了或者啥问题的 莫慌 其实并不是 今天我们就来解决一下这个问题 大致总结了以下这几种方法 1 exclude不必要文件 依次打开
  • Redis使用总结(四、处理延时任务)

    引言 在开发中 往往会遇到一些关于延时任务的需求 例如 生成订单30分钟未支付 则自动取消 生成订单60秒后 给用户发短信 对上述的任务 我们给一个专业的名字来形容 那就是延时任务 那么这里就会产生一个问题 这个延时任务和定时任务的区别究竟
  • vue router进行路由跳转并携带参数(params/query)

    在使用 router push 进行路由跳转到另一个组件时 可以通过 params 或 query 来传递参数 1 使用 params 传参 在路由跳转时传递参数 router push name targetComponent param
  • 元宇宙通证-八、人类科技发展史全景长图

    八 人类科技发展史全景长图 人类科技发展史是人类认识自然 改造自然的历史 也是人类文明史的重要组成部分 科技在人类文明进程中起着至关重要的作用 制造和使用工具以及技术的传承 是人类生存的模式 是被人类社会所实践的 人类自身的进化成功很大程度
  • Java language

    Java Java is a high level general purpose object oriented programming language The main design goals of the language wer
  • qt连接oracle数据库经验总结

    利用qt连接oracle数据库实战经验 之前公司用qt开发的产品中 使用的数据库为mysql和sql server 并未用qt连接过 oracle数据库 因此 只能通过百度查资料的方式解决问题 注意 使用qt连接oracle数据库 即使远程
  • 启元世界内推招聘(对标阿里P6-P7)

    推荐系统架构师 岗位职责 负责游戏推荐系统的需求分析 系统设计 负责应用系统平台的可行技术设计 方案 指导和优化技术选型 负责推荐算法策略线上化 系统化实现在线服务 优化平台线上性能 负责线上平台的稳定性保障 负责推动应用系统的技术升级与研
  • 懂编译真的可以为所欲为

    作者 闲鱼技术 玉缜 背景 整个前端领域在这几年迅速发展 前端框架也在不断变化 各团队选择的解决方案都不太一致 此外像小程序这种跨端场景和以往的研发方式也不太一样 在日常开发中往往会因为投放平台的不一样需要进行重新编码 前段时间我们需要在淘
  • SAE安装第三方插件

    参考官网 http sae sina com cn doc python tools html saecloud 首先要安装sae python dev 1 3 2 tar gz 然后把官网的原话copy上来 在应用目录中执行下面的命令安装
  • 点云密度计算方法matlab,点云中的几何计算及matlab源码

    1 计算法向量 2 计算曲率 曲线的曲率 curvature 就是针对曲线上某个点的切线方向角对弧长的转动率 通过微分来定义 表明曲线偏离直线的程度 数学上表明曲线在某一点的弯曲程度的数值 曲率越大 表示曲线的弯曲程度越大 曲率的倒数就是曲
  • jdbc:mysql:replication_使用Mysql的Replication功能实现数据库同步

    本文档仅在于实验Mysql的Replication功能 没有考虑权限等其他问题 用于实验的服务器和客户机请使用没有安装过Mysql的计算机 如果安装过Mysql请卸载 请按照下面的顺序依次进行 改变顺序可能导致实验失败 1 在下面地址下载免
  • 会议OA项目---我的审批(审批&会议签字)

    目录 一 会议审批 二 会议签字 三 签名裁剪 一 会议审批 我的审批 实体类MeetingAudit package com zking entity import java io Serializable import java uti
  • C语言经典例题-贷款余额

    编程计算第一 第二 第三个月还贷后剩余的贷款金额 include
  • Revit二次开发——选集

    选集 选集 用户选集 过滤的用户选集 选集 选择图元后运行外部命令获取选择的内容 Revit API中定义了单选 多选 框选等方式的用户选集 用户可以十分方便的使用鼠标和键盘完成这三种方式的图元选择 Revit API根据三种用户选集各自的
  • 设系统中有三种类型的资源(A,B,C)的五个进程(P1,P2,P3,P4,P5)。A资源的数量为17,B资源的数量为5,C资源的数量为20。在T0时刻系统状态如表所示。

    银行算法应用 题目 设系统中有三种类型的资源 A B C 的五个进程 P1 P2 P3 P4 P5 A资源的数量为17 B资源的数量为5 C资源的数量为20 在T0时刻系统状态如表所示 系统采用银行家算法实施死锁避免策略 试问 1 T0时刻
  • centos7启动服务uthorization not available. Check if polkit service is running or see debug message for

    事件经过 有一次远程帮助别人解决的一个问题 当时那个人给发了一个samba服务启动报错的截图 还有一个翻译图 报错信息中提到了一个polkit服务 下面先普及一下关于这个服务的知识 polkit是一个应用程序级别的工具集 通过定义和审核权限
  • 浅析存储引擎(3)-B-tree

    浅析日志结构的存储引擎 1 bitcask浅析日志结构的存储引擎 2 SSTable和LSM Tree 前面两篇文章介绍了比较好理解的日志结构引擎LSM Tree 但它们不是最常见的索引类型 目前最广泛使用的索引结构是B tree B tr