首页 > 其他分享 >CMU 15-445(Fall 2023) Project2 Extendible Hash Index个人笔记

CMU 15-445(Fall 2023) Project2 Extendible Hash Index个人笔记

时间:2024-02-02 16:13:48浏览次数:36  
标签:Index 15 idx auto bucket uint32 Fall directory page

Task #1 - Read/Write Page Guards踩坑

BasicPageGuard的移动构造函数:

  1. 两个PageGuard有可能指向同一个页面,要先判断是否指向同一个页面,如果指向同一个页面直接返回。
  2. 由于需要将page_属性指向另一个页面,因此要先调用Drop方法放弃对当前指向页面的使用。

BasicPageGuard的Drop方法:

  1. 对于同一个PageGuard,Drop方法应该只生效一次,即Drop方法只在第一次调用时生效,通过设置一个标志位即可。
  2. 调用UnpinPage方法时,传入的应该是PageGuard的is_dirty_属性,而不是其指向的page的is_dirty_属性。

ReadPageGuard的Drop方法:

  1. 要先释放锁,再调用BasicPageGuardDrop方法。 如果先调用BasicPageGuardDrop方法,那么页面可能就会被缓冲管理器淘汰掉,替换为一个新的页面,此时再释放锁会导致新加载进来的页面的锁被释放。

Task #2 - Extendible Hash Table Pages踩坑

ExtendibleHTableHeaderPage

Init方法一定要初始化directory_page_ids_,因为directory是否存在的判断条件是:

header_page->GetDirectoryPageId(dir_index) == static_cast<uint32_t>(INVALID_PAGE_ID)

同时测试函数会调用VerifyIntegrity方法,如果未初始化directory_page_ids_,那么会导致出错。

Init方法实现参考:

void ExtendibleHTableHeaderPage::Init(uint32_t max_depth) {
  max_depth_ = max_depth;
  auto size = MaxSize();
  for (uint32_t i = 0; i < size; i++) {
    directory_page_ids_[i] = INVALID_PAGE_ID;
  }
}

ExtendibleHTableDirectoryPage

同样的,Init方法要初始化bucket_page_ids_属性。

Task #3 - Extendible Hashing Implementation踩坑

算法的实现可以参考下面的文章和视频。
Extendible Hash Table 算法实现

Extendible Hashing (Dynamic approach to DBMS)

Extendible Hash Table讲解视频

Insert算法流程

  1. 加载header
  2. 根据哈希值计算directory_index,然后根据directory_index获取directory_page_id
  3. 如果directory_page_id无效,则需要新建一个directory,并且将键值插入到新创建的directory中。 如果directory_page_id有效,则加载对应的directory,并且加键值插入到对应的directory
插入到新创建的directory:
  1. 利用bpm_->NewPageGuarded方法创建一个新的directorybucket
  2. 初始化directorybucket
  3. bucket_page_id插入directory的下标0中,设置下标0的局部深度为0
  4. 将键值对插入到bucket
  5. directory保存到header
插入到已有的directory:
  1. 根据哈希值计算bucket_idx,并且加载bucket
  2. 判断bucket是否已满,若未满,则执行步骤8;若已满,则接着执行步骤3
  3. 判断bucket_idx对应的局部深度是否等于全局深度,如果等于全局深度,接着执行步骤4,否则执行步骤6
  4. 判断directory是否已满,即Size()>=MaxSize(),若是directory已满,则直接返回falsedirectory未满,接着执行步骤5。
  5. 增加全局深度
  6. 分裂bucket,具体分裂流程参照后面详细步骤
  7. 回到步骤1重新尝试插入
  8. 调用bucketInsert方法将键值插入即可
分裂bucket流程
  1. bucket_idx对应的局部深度加一
  2. 创建一个新的bucket,并且初始化
  3. 将旧的bucket中的数据重新分配到两个bucket中,遍历旧的bucket中的所有元素,利用新的局部深度计算new_bucket_idx,如果new_bucket_idx等于bucket_idx,那么数据仍然插入到旧的bucket中,否则插入到新的bucket中
  4. 重新分配directory指向的bucket,具体算法如下:
// 参考文章: https://www.inlighting.org/archives/extendible-hash-table-algorithm

// 辅助函数
auto ExtendibleHTableDirectoryPage::GetImageBucketIndex(uint32_t bucket_idx) const -> uint32_t {
  uint32_t local_depth = local_depths_[bucket_idx];
  return bucket_idx ^ (1 << (local_depth - 1));
}

// 分配算法
auto image_bucket_idx = directory_page->GetImageBucketIndex(bucket_idx);
uint32_t diff = 1 << directory_page->GetLocalDepth(bucket_idx);

for (uint32_t i = bucket_idx; i >= 0; i -= diff) {
	directory_page->SetBucketPageId(i, directory_page->GetBucketPageId(bucket_idx));
	directory_page->SetLocalDepth(i, directory_page->GetLocalDepth(bucket_idx));
	if (i < diff) {
  		break;
	}
}
for (uint32_t i = bucket_idx+diff; i < directory_page->Size(); i += diff) {
	directory_page->SetBucketPageId(i, directory_page->GetBucketPageId(bucket_idx));
	directory_page->SetLocalDepth(i, directory_page->GetLocalDepth(bucket_idx));
}
for (uint32_t i = image_bucket_idx; i >= 0; i -= diff) {
    directory_page->SetBucketPageId(i, new_bucket_page_id);
    directory_page->SetLocalDepth(i, directory_page->GetLocalDepth(bucket_idx));
    if (i < diff) {
      break;
    }
}
for (uint32_t i = image_bucket_idx+diff; i < directory_page->Size(); i += diff) {
    directory_page->SetBucketPageId(i, new_bucket_page_id);
    directory_page->SetLocalDepth(i, directory_page->GetLocalDepth(bucket_idx));
}

Task #4 - Concurrency Control踩坑

Task #1中,实现了FetchPageWriteFetchPageRead,这两个方法都会加锁,因此不需要额外的锁,在InsertRemove方法中,通过FetchPageWrite来获取页面,在GetValue方法中,通过FetchPageRead方法获取页面即可实现并发安全。页面使用完以后,在适当的时候就可以调用Drop方法。
例如Insert方法:

template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::Insert(const K &key, const V &value, Transaction *transaction) -> bool {
  // ...
  auto header_guard = bpm_->FetchPageWrite(header_page_id_);
  auto header_page = header_guard.template AsMut<ExtendibleHTableHeaderPage>();
  //...
  auto directory_guard = bpm_->FetchPageWrite(directory_page_id);
  auto directory_page = directory_guard.template AsMut<ExtendibleHTableDirectoryPage>();
  // ...
  auto bucket_guard = bpm_->FetchPageWrite(directory_page->GetBucketPageId(bucket_idx));
  auto bucket_page = bucket_guard.template AsMut<ExtendibleHTableBucketPage<K, V, KC>>();
}

通过截图

标签:Index,15,idx,auto,bucket,uint32,Fall,directory,page
From: https://www.cnblogs.com/fenfeng9/p/18003336

相关文章

  • CMU 15-445(Fall 2023) Project1 BUFFER POOL个人笔记
    PROJECT#1-BUFFERPOOL总结本文章不涉及实验要求实现的方法的具体代码,且只包括基础部分的内容。Project1只做了基础部分,没有做针对排行榜的优化。Project1基础部分不算难,但Bustub中只提供了简单的测试样例,通过了本地的测试后提交到gradescope可能拿不了满分,需要根据gradesco......
  • 痞子衡嵌入式:我入选了2023年度与非网(eefocus)最佳创作者Top15
    最近收到了「与非网」发来的2023年度最佳创作者证书,证书做得一如既往地有质感,这是与非网第二次给痞子衡发证书了,足见与非网对痞子衡的认可。与非网自2021年起,每年都会评选一次年度创作者,第一年叫星选创作者TOP10,第二年叫影响力创作者TOP10,第三年也就是今年变成了最佳创......
  • 关于Spring5新增的Indexed注解
    前言如果我们应用中使用@ComponentScan注解扫描的package包含的类很多的时候,Spring解析耗时就会很多,相应的应用启动时间也就更长,Spring5.0引入了一个新的注解@Indexed,它可以为Spring的模式注解添加索引,以提升应用启动性能。使用<dependency><groupId>org.springframewor......
  • 无涯教程-lastIndexOf()函数
    此方法返回最后一次出现的指定值的调用字符对象内的索引,如果没有找到该值,则从fromIndex或-1开始搜索。lastIndexOf()-语法string.lastIndexOf(searchValue[,fromIndex])searchValue  - 表示要搜索的值的字符串。fromIndex   - 调用字符串中开始搜索的位......
  • pandas - reset_index() 函数 将Series对象转换为一个新的DataFrame
    #df=pd.read_excel(r"D:\PyCharm\年度数据处理\1月设备离线01.xlsx",sheet_name='Sheet2')#value_counts=df['解除时间'].value_counts().reset_index()#print(value_counts)这段代码的作用是对DataFrame中的"解除时间"列进行值计数,并将结果保存在一个新的DataFrame......
  • [转帖]Open JDK 8.0_152-b16 崩溃 : [libzip.so+0x12522] newEntry+0x62
    一.问题描述在执行spark任务的时候,JVM崩溃.崩溃dump日志:##AfatalerrorhasbeendetectedbytheJavaRuntimeEnvironment:##SIGBUS(0x7)atpc=0x00007f9adacb9522,pid=107874,tid=0x00007f9add417700##JREversion:Java(TM)SERuntimeEnvironme......
  • Dash 2.15版本新特性介绍
    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master大家好我是费老师,Dash不久前发布了其2.15.0版本,新增了一些实用的特性,下面我们就来一起get其中的重点......
  • 没闲着系列 15
    今天tasksaas更新了几个问题,现在在manage.html页面加入统一的消息提醒,整体可接受消息了.在dashboard页面加入点击人员头像进行聊天,发送提醒信息,另一边可进行回复.......
  • CF1575I Illusions of the Desert
    分析首先发现此题的式子一看就不是很友好。所以尝试化简。原式:\(max(|a_u+a_v|,|a_u-a_v|)\)。分类讨论:当\(a_u>0,a_v>0\)时,显然有原式\(=a_u+a_v\);当\(a_u>0,a_v<0\)时,\(|a_u-a_v|=|a_u+|a_v||\),\(|a_u+a_v|=|a_u-|a_v||\)。肉......
  • 洛谷 P3976 [TJOI2015] 旅游
    这出题人语言表达能力真的感人……希望你们看完这篇题解后不要觉得我的语言表达能力和出题人不相上下。题目大意给定一棵有点权的树,每次询问从\(u\)到\(v\)的路径上后经过的点权减去先经过的点权的最大值,再把这条路径上所有点的点权加上一个给定的数。分析俗话说得好:如果......