CMU15-445-Spring-2023-Project #2 - B+Tree

前置知识:参考上一篇博文 CMU15-445-Spring-2023-Project #2 - 前置知识(lec07-010)

CHECKPOINT #1

Task #1 - B+Tree Pages

实现三个page class来存储B+树的数据。

  • B+Tree Page
    • internal page和leaf page继承的基类,只包含两个子类共享的信息;
    • image.png
    • Impl:
      • src/include/storage/page/b_plus_tree_page.h
      • src/storage/page/b_plus_tree_page.cpp
  • B+Tree Internal Page
    • 一个内部页面存储 m 个有序键和 m+1 个指向其他 B+Tree 页面的子指针(作为 page_id)。这些键和指针在内部表示为一个 key/page_id 对数组。由于指针的数量不等于键的数量,因此第一个键被设置为无效,查找应始终从第二个键开始
    • 在任何时候,每个内部页面都应至少满一半。在删除过程中,可以合并两个半满的页面,或者重新分配键和指针以避免合并。在插入过程中,可以将一个完整的页面分割成两个,也可以重新分配键和指针以避免分割;
    • Impl:
      • src/include/storage/page/b_plus_tree_internal_page.h
      • src/storage/page/b_plus_tree_internal_page.cpp
  • B+Tree Leaf Page
    • leaf page存储 m 个有序键及其 m 个相应的值。值应始终是tuple实际存储位置的 64 位 record_id;参阅 src/include/common/rid.h 中的 RID 类。leaf page对k/v对数量的限制与内部页面相同,并应遵循合并、拆分和重新分配键的相同操作;
    • Impl:
      • src/include/storage/page/b_plus_tree_leaf_page.h
      • src/storage/page/b_plus_tree_leaf_page.cpp

每个 B+Tree 的leaf/internal page都与缓冲池获取的内存页的内容(即 data_ 部分)相对应。每次读取或写入leaf/internal page时,必须先从缓冲池中获取该页(使用其唯一的 page_id),然后 reinterpret cast 成leaf/internal page,并在读取或写入该页后将其unpin。

Task #2a - B+Tree Insertion and Search for Single Values

Impl:
src/storage/index/b_plus_tree.cpp

如果插入改变了根页面的 ID,则必须更新 B+Tree 索引头页面中的 root_page_id。为此,可以访问在构造函数中给出的 header_page_id_ page。然后,通过使用 reinterpret cast,将该页面解释为 BPlusTreeHeaderPage(来自 src/include/storage/page/b_plus_tree_header_page.h),并从这里更新根页面 ID。实现 GetRootPageId(目前默认返回 0)。
使用 project 1 中的page guard类来帮助防止同步问题。在访问页面时使用 FetchPageBasic(定义于 src/include/storage/page/)。以后在task 4 中实施并发控制时,可以根据需要将其改为使用 FetchPageRead 和 FetchPageWrite。
可以选择使用 Context 类(定义于 src/include/storage/index/b_plus_tree.h)来跟踪已读取或写入的页面(通过 read_set_ 和 write_set_ 字段),或存储需要递归传递到其他函数的其他元数据。
只需要在插入或删除时使用 write_set_。可能不需要使用 read_set_,这取决于实现。
在context中存储根页面 id,并在修改 B+Tree 时获取头页面的写保护。
write_set_ 的尾部保存当前节点的父节点,它应该包含访问路径上的所有节点。
如果要拆分节点(根节点除外),要确保 write_set_ 中至少还有一个节点。
要解锁header page,只需将 header_page_ 设为 std::nullopt。要解锁其他页面,只需从 write_set_ 中弹出即可。
插入后,当值的数量达到 max_size 时,分割叶节点;插入前,当值的数量达到 max_size 时,分割内部节点。这将确保在进行 InsertIntoLeaf 等操作后再重新分配时,插入叶节点不会导致页面数据溢出;这也将防止内部节点只有一个子节点。
当叶页面无法获取同级页面的latch时,需要抛出一个 std::exception 异常,以避免潜在的死锁。
每个线程将始终从头页到底部获取锁存器。释放锁存器时,请确保以相同的顺序(从页眉到底部)释放。
在插入时,即使拥有父节点的锁,也应始终获取子节点的锁。想想这样一种情况:一些线程正在使用读锁从叶子页中获取值,而另一些线程正在更新页面(例如,在聚合时)。如果不加锁,就会出现race。

  • GetValue()
    • 使用ReadPageGuard访问页面。通过header_page_id_访问header page,header page的root_page_id_指向根节点的第一个k/v对;
    • 当获取了根节点的页面的latch后,释放header page的latch;
    • 通过二分搜索key在页面中的位置,迭代向下查找到leaf page,然后找到leaf page中相应的value(rid)。
  • Insert()
    • 同样,先获取根页面,若根为空,通过NewPageGuarded获取一个新页面,然后插入;
    • 若根节点不为空,通过write_set_维护向下搜索的path,直到到达leaf page,并且通过prev_和next_维护路径上节点的左右兄弟节点(插入分裂优化);
    • 若搜索过程中某个internal page的size小于max size,就可以将write_set_中的节点弹出,因为即使叶子节点需要分裂,internal page需要插入新k/v对,size也是够的;
    • 插入分裂优化:若leaf page插入后超过了max size,但是其兄弟节点没满,会将最左/右记录移动到其兄弟节点上,默认先向左移动;(参考InnoDB,充分利用索引页,还有一种方法就是在特定的递增key插入情况下,如果检测到三个连续递增的key,那么就不进行分裂,而是直接往右新建一个页面插入,避免频繁分裂)常规分裂就是50%。
    • leaf page分裂会产生新的k/v,继续向上往internal page插入(根据write_set_维护的path),同样进行插入分裂优化;
    • 若write_set_遍历完后还需要向上插入,那么通过NewPageGuarded获取新页面作为根节点,然后更新即可;

CHECKPOINT #2

Task #2b - B+Tree Deletions

支持key的删除,包括页面的合并或重新分配键。与插入一样,如果根页面发生变化,必须正确更新 B+Tree 的根页面 ID。
Impl:
src/storage/index/b_plus_tree.cpp

  • Remove()
    • 几乎与Insert同样的思路,进行合并优化,优先从兄弟节点拉取单个k/v到本节点;

Task #3 - An Iterator for Leaf Scans

添加一个 C++ 迭代器,以有效支持对leaf page中的数据进行顺序扫描。基本思路是存储同胞指针,以便高效地遍历leaf page,然后实现一个迭代器,按顺序遍历每个leaf page中的每个键值对。

  • C++17 style;
  • isEnd():返回此迭代器是否指向最后一个键/值对;
  • operator++():移动到下一个键/值对;
  • operator*():返回该迭代器当前指向的键/值对;
  • operator==():返回两个迭代器是否相等;
  • operator!=():返回两个迭代器是否不相等;
  • Begin() & End():返回最左/右的leaf page的迭代器;

Impl:
src/include/storage/index/index_iterator.h
src/index/storage/index_iterator.cpp
src/storage/index/b_plus_tree.cpp
IndexIterator内部维护三个值:bpm、page id、page内部index。

Task #4 - Concurrent Index

FetchPageWrite or FetchPageRead

实验结果

image.pngimage.png

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

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

相关文章

C语言辨析——深入理解字符常量与表达式

1. 问题 今天看到一个题目,截图如下。 从答题情况来看,本题的答案是B,那么就意味着A、C、D是错的。但我认为这4个选项都是对的。当然,如果要从4个选项中挑选一个的话,那还是选择B妥当一些。 2. 分析 字符常量的定义…

【漏洞复现】优卡特脸爱云一脸通智慧管理平台权限绕过漏洞CVE-2023-6099(1day)

漏洞描述 脸爱云一脸通智慧管理平台1.0.55.0.0.1及其以下版本SystemMng.ashx接口处存在权限绕过漏洞,通过输入00操纵参数operatorRole,导致特权管理不当,未经身份认证的攻击者可以通过此漏洞创建超级管理员账户。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当…

CAN总线报文格式———扩展数据帧

扩展数据帧由帧起始、仲裁段、控制段、数据段、CRC段、ACK段、帧结束等组成。 一、总线空闲(Bus Idle) CAN总线空闲时,总线上会输出持续的高电平“1”。当总线空闲时任何连接的单元都可以开始发送新的报文。 二、帧起始(Start o…

鱼哥赠书活动第⑤期:《ATTCK视角下的红蓝对抗实战指南》《智能汽车网络安全权威指南》上下册 《构建新型网络形态下的网络空间安全体系》《Kali Linux高级渗透测试》

鱼哥赠书活动第⑤期: 《ATT&CK视角下的红蓝对抗实战指南》1.1介绍: 《智能汽车网络安全权威指南》上册1.1介绍: 《智能汽车网络安全权威指南》下册1.1介绍: 《构建新型网络形态下的网络空间安全体系》1.1介绍: 《K…

遭受慢速连接攻击怎么办?怎么预防

慢速连接攻击是一种常见的网络攻击方式,其原理是利用HTTP协议的特性,在建立了与Http服务器的连接后,尽量长时间保持该连接,不释放,达到对Http服务器的攻击。 慢速连接攻击的危害包括以下几个方面: 1.资源…

推荐一款.NET开发的物联网开源项目

物联网(IoT)是一个正在快速发展的技术领域,它涉及到各种设备、物体和系统的互联。所以各种物联网平台和物联网网关项目层出不穷,在物联网(IoT)领域,.NET平台扮演着重要的角色。作为一款广泛使用…

管理软件供应链中网络安全工具蔓延的三种方法

软件开发组织不断发展,团队成长,项目数量增加。技术堆栈发生变化,技术和管理决策变得更加分散。 在这一演变过程中,该组织的 AppSec 工具组合也在不断增长。在动态组织中,这可能会导致“工具蔓延”。庞大的 AppSec 工…

Colab 谷歌免费的云端Python编程环境初体验

最新在学习AIGC的过程中,发现很多教程,demo使用到了Colab这个谷歌工具。 Colab 是什么? Google Colab是一个强大且免费的云端Python编程环境,为学生、研究人员和开发者提供了一个便捷的平台来开展数据科学、机器学习和深度学习项…

《最新出炉》系列入门篇-Python+Playwright自动化测试-9-页面(page)

1.简介 通过前边的讲解和学习,细心认真地小伙伴或者童鞋们可能发现在Playwright中,没有Element这个概念,只有Page的概念,Page不仅仅指的是某个页面,例如页面间的跳转等,还包含了所有元素、事件的概念&#…

redis夯实之路-主从复制详解

Redis中可以通过执行slaveof命令或者设置slaveof选项,让一个服务器区复制另一个服务器,被复制的为主服务器,复制的为从服务器。 复制 Redis中可以通过执行slaveof命令或者设置slaveof选项,让一个服务器区复制另一个服务器&#…

LLVM系列(1): 在微软Visual Studio下编译LLVM

参考链接: Getting Started with the LLVM System using Microsoft Visual Studio — LLVM 18.0.0git documentation 1.安装visualstudio,版本需要大于vs2019 本机环境已安装visual studio2022,省略 2安装Makefile,版本需要大…

C++力扣题目617--合并二叉树

给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠&#…

YOLOv5改进 | 二次创新篇 | 结合iRMB和EMA形成全新的iEMA机制(全网独家创新)

一、本文介绍 本文给大家带来的改进机制是二次创新的机制,二次创新是我们发表论文中关键的一环,为什么这么说,从去年的三月份开始对于图像领域的论文发表其实是变难的了,在那之前大家可能搭搭积木的情况下就可以简单的发表一篇论文,但是从去年开始单纯的搭积木其实发表论…

Spring Boot - JaCoCo Code Coverage

文章目录 概述如何集成pom添加插件Code Demo排除不相关的类CI/CD中使用完整POM 概述 JaCoCo(Java Code Coverage)是一个开源的Java代码覆盖率工具,它主要用于评估Java程序的测试完整性。通过跟踪测试过程中执行的代码,JaCoCo能够…

【期末不挂科-C++考前速过系列P6】大二C++实验作业-模板(4道代码题)【解析,注释】

前言 大家好吖,欢迎来到 YY 滴C考前速过系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY的《…

大学期末考前复习卷(上)

第一题: 泰勒展开式求sin(x) 【问题描述】 已知sin(x)的泰勒展开式为: sin(x) x/1! - x^3/3! x^5/5! - x^7/7! …… 当某一项的绝对值小于ξ时,停止计算。 输入x及ξ的值,输出sin(x)的值,小数点后保留5位小数。…

第8章-第6节-Java中字符流的缓冲流

1、在说正题之前,先说一个小细节,不管是字节流还是字符流都要注意这个细节,具体看这篇博文:关于Java的IO流里面的方法read()的小细节 2、字符流的缓冲流: 1)、BufferedWriter 方法名说明void newLine()写…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《与新能源互补和独立参加多级市场的抽蓄电站容量分配策略》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题涉及到抽蓄电站在能源系统中的角色,特别是在多级市场中的参与,并强调了新能源的互补性以及抽蓄电站的独立性。下面我将…

如何在企业中实施自适应人工智能?

人工智能不再是企业的选择。很快,它也将不再是一个区分因素。商业中的适应性人工智能正在改变格局。根据最近的统计数据,95%的企业以上都在追求人工智能。 因此,为了确保你拥有竞争优势,你必须期待先进的人工智能选项。适应性就是…

在线的货币兑换平台源码下载

在线的货币兑换平台,可帮助全球各地的个人和企业将货币从一种货币兑换为另一种货币。该货币兑换平台是 Codecanyon 中最先进的脚本。 源码下载:https://download.csdn.net/download/m0_66047725/88728084