数据库课程 CMU15-445 2023 Fall Project-2 Extendible Hash Index

0 实验结果

在这里插入图片描述
tips:完成项目的前提不需要一定看视频

1 数据结构:扩展哈希

扩展哈希
解释下这张图:
图中header的最大深度2,directory最大深度2,桶的容量2。
最开始的时候只有一个header。
插入第一个数据,假设这个数据对应的哈希值是00…100
header的索引使用的是哈希值的MSB,即高位,因为header深度2,所以直接取高两位,即0.
此时header[0]并没有指向的directory,所以需要先new page创建目录页面,创建出的目录页面,默认gd,即全局深度应该为0.
目录页面实际指向页面的索引个数:1 << gd,即默认1个索引,此时索引到的bucket id为非法页面,索引需要new page创建桶页面。
将哈希值00…100对应的键值对存入桶中,并更新header,directory,bucket之间的索引关系。
不断插入数据,将导致桶溢出,此时就需要进行分类,也即图中下面部分的情况。
需要注意的是,当从directory索引bucket的时候使用的是哈希值的LSB,而由几个位索引则由directory的gd决定。

2 任务要求

2.1 Read/Write Page Guards

需要实现 BasicPageGuard, ReadPageGuard, WritePageGuard 的移动构造函数,移动赋值操作,析构函数。
移动构造,移动赋值就是转移guard的所有权,但是移动赋值操作,需要释放本来的资源,接管传入的that指向。

2.1.1 需要注意的地方
  1. WritePageGuard和ReadPageGuard的移动赋值操作,需要先drop,再赋值新的guard。
  2. FetchPageRead和FetchPageWrite返回guard之前,一定要加读/写锁。
2.2 Extendible Hash Table Pages

在这个任务中需要实现header,directory,bucket页面的结构。
header索引directory使用的是MSB
directory索引bucket使用的是LSB

2.2.1 重点说一下directory page
// 注意:全局深度设置为0,本地深度设置为0
ExtendibleHTableDirectoryPage::Init// 1. 插入时,桶满分裂,传入原桶索引,返回新桶索引
// 2. 删除时,获取当前桶索引分裂时产生的对称索引,用于检查一方是否为空桶
ExtendibleHTableDirectoryPage::GetSplitImageIndex// 增加深度,需要拷贝一半,directory目录扩大一倍
ExtendibleHTableDirectoryPage::IncrGlobalDepth// 什么时间可以缩减目录? directory目录大小内,全部满足ld < gd
ExtendibleHTableDirectoryPage::CanShrink()
2.3 Extendible Hashing Implementation

在这个任务中就需要使用 2.2 中准备好的API来实现DiskExtendibleHashTable的构造函数,读值,插入和删除。

2.3.1 插入

第一部分:扩展哈希的介绍,相信对Insert的流程有一个了解。
插入时,如果directory页面不存在,需要先创建directory页面。
如果directory页面存在,需要根据全局深度gd个LSB位索引桶页面,如果桶满,需要进行分裂。
这里有两种情况:

  1. 全局深度大于局部深度
    只进行桶分裂
  1. 全局深度等于局部深度
    目录扩展+桶分裂

这里只对第二种情况分析(其实也只比1多一个操作):

如果全局深度==局部深度,需要增加全局深度,如果全局深度已经最大,则表示扩展哈希已满。增加局部深度ld,分裂过程中对原桶存在的所有key重新分配桶。

存在一种情况: 全部的key又被分到同一个桶中了,此时仍然无法插入新key,所以,插入操作是一个while操作,如果扩展哈希未满,应该继续分裂,尝试插入。

产生的新桶,需要使用UpdateDirectoryMapping更新directory的下标指向新的page_id。
这里提供下实现:

template <typename K, typename V, typename KC>
void DiskExtendibleHashTable<K, V, KC>::UpdateDirectoryMapping(ExtendibleHTableDirectoryPage *directory,uint32_t new_bucket_idx, page_id_t new_bucket_page_id,uint32_t new_local_depth, uint32_t local_depth_mask) {// throw NotImplementedException("DiskExtendibleHashTable is not implemented");uint32_t val = 0;  // 当gd为0,返回索引0for (uint32_t i = 0; i < new_local_depth; i++) {val <<= 1;val |= 1;}uint32_t start_idx = new_bucket_idx & val;for (uint32_t idx = start_idx; idx < directory->Size(); idx += (1 << new_local_depth)) {directory->SetBucketPageId(idx, new_bucket_page_id);directory->SetLocalDepth(idx, new_local_depth);}
}

另外需要注意的是:不支持重复键插入,所以一定要先Lookup检查,不存在时再进入insert操作。

2.3.2 查询

查询是最简单的了,如果后面遇到bug,可以在这个函数中添加以下代码,进行调试。
使用./test/extendible_htable_test >> mylog.txt将log重定向,看下哪里不对劲。

directory_page->PrintDirectory();
bucket_page->PrintBucket();
2.3.3 删除

删除成功的时候需要检查 桶 是否空了,空的话,需要进行合并操作。

在这里插入图片描述
写这个函数的时候,我遇到了合并上的疑惑:

  1. project 2中第三条提到了递归合并,也即如果合并后仍未空,需要继续合并。
  2. 合并后directory索引的维护问题,一开始我以为只需要修改原来空桶的索引指向非空的桶。

所以我尝试看看网上的文章,看到两点注意:

  1. 当前桶和对应的split image桶,有一个为空就需要合并。
  2. 更新directory索引,需要将所有指向空桶的索引修改(这个借助完成的UpdateDirectoryMapping实现)

看了两眼感觉和自己的思路不一样,懒得看了,还是自己写吧。
所以删除的流程应该是:
获取当前桶对应的split 桶(如果存在的话),

  1. 当前桶或者split桶有一个为空,就需要删除空桶
  2. 更新索引。
// 1. 释放空桶
bucket_guard.Drop();
bpm_->DeletePage(bucket_page_id);
// 2. 更新directory_page
// 可能多个下标指向删除的桶 2^(gd-ld)
directory_page->DecrLocalDepth(split_idx);
UpdateDirectoryMapping(directory_page, bucket_idx, split_bucket_page_id,directory_page->GetLocalDepth(split_idx), 0);
  1. CanShrink缩减目录
  2. 重新获取页,为了递归删除,需要更新bucket_guardsplit_bucket_guard
2.3.3.1 注意

注意后面为了并发控制使用FetchPageWrite时候,第4步,重新获取页,需要先drop页面进行解锁,否则重新获取页时候可能会发生死锁。

split_bucket_guard.Drop();
bucket_guard.Drop();
2.4 Concurrency Control

将前面获取页面的操作FetchPageBasic修改为FetchPageWrite或者FetchPageRead,并选择合适的时机drop解锁。

3 知识总结

这一节中比较有意思的是page_guard中构造函数的实现。
另外非类型模板参数
允许将具体的值(而不是类型)传递给模板。这种参数通常是整型、指针、枚举等,能够在编译期提供具体的值,而不是运行时。

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

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

相关文章

[自然语言处理]RNN

1 传统RNN模型与LSTM import torch import torch.nn as nntorch.manual_seed(6)# todo:基础RNN模型 def dem01():参数1&#xff1a;input_size 每个词的词向量维度&#xff08;输入层神经元的个数&#xff09;参数2&#xff1a;hidden_size 隐藏层神经元的个数参数3&#xff1a…

【puppeteer】wvp-puppeteer制作 过程

目录 最后的结论 制作windows&ubuntu的docker 重启桌面上的docker 命令重启 通过 Docker Desktop 图形界面重启 制作centos docker 测试 参考文档 最后的结论 ubuntu && windows 使用 dualvenregistry:5000/wvp-puppeteer:1.0 centos7 使用&#xff1a;…

RabbitMQ事务模块

目录 消息分发​​​​​​​ 负载均衡 幂等性保障 顺序性保障 顺序性保障方案 二号策略:分区消费 三号策略:消息确认机制 四号策略: 消息积压 RabbitMQ集群 选举过程 RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制&#xff0c;要么全部成功&#xff0c;要么全…

Java——数组的定义与使用

各位看官&#xff1a;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论&#xff0c;感谢您的支持&#xff01;&#xff01;&#xff01; 一&#xff1a;数组的概念以及定义,初始化 1.1&#xff1a;数组概念以及定义 数组概念&#xff1a;可以看成…

四边形网格生成算法:Q-Morph(三)底边生成四边形

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 参考论文&#xff1a;Q-Morph an indirect approach to advancing front quad meshing ε − π − θ ∈ ⋅ \varepsilon - \pi - \theta \in \cdot ε−π−θ∈⋅ …

通过redis实现高性能计费处理逻辑

计费服务一般都是跟资金相关&#xff0c;所以它在系统中是非常核心的模块&#xff0c;要保证服务的高可用、事务一致性、高性能。服务高可用需要集群部署&#xff0c;要保证事务一致性可以通过数据库来实现&#xff0c;但是只通过数据库却很难实现高性能的系统。 这篇文章通过使…

解锁5 大无水印热门短视频素材库

想让你的抖音视频更出彩吗&#xff1f;想知道那些爆款视频的素材源头吗&#xff1f;快来了解以下 5 个超棒的视频素材下载平台。 蛙学网 国内的视频素材佼佼者&#xff0c;有大量 4K 高清且无水印的素材&#xff0c;自然风光、情感生活等类别任你选&#xff0c;不少还免费&…

关于wordpress建站遇到的问题

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

Spring WebFlux 核心原理(2-1)

1、Spring 响应式编程 1.1、早期响应式解决方案 响应式编程是构建响应式系统的主要候选方案。Spring 4.x 引入了 ListenableFuture 类&#xff0c;它扩展了 Java Future&#xff0c;并且可以基于 HTTP 请求实现异步执行操作。但是只有少数 Spring 4.x 组件支持新的 Java 8 Com…

瑞芯微RK3566/RK3568 Android11使用OTA升级固件方法,深圳触觉智能鸿蒙开发板演示,备战第九届华为ICT大赛

本文介绍瑞芯微RK3566/RK3568在Android11系统OTA升级固件方法&#xff0c;使用触觉智能的Purple Pi OH鸿蒙开发板演示&#xff0c;搭载了瑞芯微RK3566&#xff0c;Laval官方社区主荐&#xff01; 1、OTA包生成 在源码根目录上执行以下命令编译OTA包 # make installclean # …

【华为HCIP实战课程七】OSPF邻居关系排错MTU问题,网络工程师

一、MTU MUT默认1500,最大传输单元,一致性检测 [R3-GigabitEthernet0/0/1]mtu 1503//更改R3的MTU为1503 查看R3和SW1之间的OSPF邻居关系正常: 默认华为设备没有开启MTU一致性检测! [R3-GigabitEthernet0/0/1]ospf mtu-enable //手动开启MTU检测 [SW1-Vlanif30]ospf mtu…

【详细教程】如何使用YOLOv11进行图像与视频的目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

《数字信号处理》学习08-围线积分法(留数法)计算z 逆变换

目录 一&#xff0c;z逆变换相关概念 二&#xff0c;留数定理相关概念 三&#xff0c;习题 一&#xff0c;z逆变换相关概念 接下来开始学习z变换的反变换-z逆变换&#xff08;z反变化&#xff09;。 由象函数 求它的原序列 的过程就称为 逆变换。即 。 求z逆变换…

linux线程 | 线程的控制(二)

前言&#xff1a; 本节内容是线程的控制部分的第二个小节。 主要是列出我们的线程控制部分的几个细节性问题以及我们的线程分离。这些都是需要大量的代码去进行实验的。所以&#xff0c; 准备好接受新知识的友友们请耐心观看。 现在开始我们的学习吧。 ps:本节内容适合了解线程…

如何批量从sql语句中提取表名

简介 使用的卢易表 的提取表名功能&#xff0c;可以从sql语句中批量提取表名。采用纯文本sql语法分析&#xff0c;无需连接数据库&#xff0c;支持从含非sql语句的文件文件中提取&#xff0c;支持各类数据库sql语法。 特点 快&#xff1a;从成百个文件中提取上千个表名只需1…

JAVA开发中SpringMVC框架的使用及常见的404问题原因以及SpringMVC框架基于注解的开发实例

一、JAVA开发中SpringMVC框架的使用及常见的404问题原因 使用SpringMVC建立一个web项目&#xff0c;在IDEA中file->new->project建立一个空项目project。不用选择create from archetype从模板创建。然后在项目的pom.xml中添加公共的依赖包括org.springframework&#xff…

400行程序写一个实时操作系统RTOS(开篇)

笔者之前突发奇想&#xff0c;准备写一个极其微小的实时操作系统内核&#xff0c;在经过数天的努力后&#xff0c;这个RTOS诞生了。令读者比较意外的是&#xff0c;它的程序只有400行左右。但就是这短短的400行&#xff0c;完成了动态内存管理、多线程、优先级、临界区、低功耗…

【原创】Android Studio 中安装大模型辅助编码插件:通义灵码

在 Android Studio 中内置了 Ginimi 预览版&#xff0c;但需要“加速器”才可使用。 在国内有平替的软件同样可以使用&#xff0c;比如 阿里的通义灵码&#xff0c;智谱的CodeGeeX等&#xff0c;从功能和使用上来说都是大同小异。 这里我们以通义灵码为例来讲解其安装和使用 通…

最新Prompt预设词指令教程大全ChatGPT、AI智能体(300+预设词应用)

使用指南 直接复制在AI工具助手中使用&#xff08;提问前&#xff09; 可以前往已经添加好Prompt预设的AI系统测试使用&#xff08;可自定义添加使用&#xff09; SparkAi系统现已支持自定义添加官方GPTs&#xff08;对专业领域更加专业&#xff0c;支持多模态文档&#xff0…

github下载文件的两种方式(非git形式)

1.以下面的图为例 &#xff0c;可以直接点击右上方的绿色Code按键&#xff0c;在弹出的列表中选择Download Zip选项&#xff0c;即可下载。 2.如果下载的是单独的某一个文件&#xff0c;则可以按照下图的格式点击下图所示的那个下载的图标即可。