๐Ÿ˜‚Expand2: Delete

1. ๅˆ ้™ค็ฎ—ๆณ•ๅŽŸ็†

cmu่ฟ™้‡Œ็ป™ไบ† ๆผ”็คบ็ฝ‘็ซ™

ๅ…ณไบŽๆ•ดไธชๅˆ ้™ค็ฎ—ๆณ•็š„่ฎฒ่งฃ่ฟ™ไธช ppt ่ฎฒ็š„ๆฏ”่พƒๆธ…ๆฅš

็ฎ—ๆณ•ๆ่ฟฐ่งไธ‹่กจ

image-20210121112759338

ไปฅๅŠไธ‹ๅ›พ

img

2 ๅˆ ้™ค็ฎ—ๆณ•ๅฎž็Žฐ

2.1 ็ฌฌไธ€ๆญฅ : ๆ‰พๅˆฐๅŒ…ๅซ็›ฎๆ ‡key็š„leaf node่ฟ›่กŒๅˆ ้™ค

  1. ๆ‰พๅˆฐๅŒ…ๅซ็›ฎๆ ‡key็š„ leaf node

  2. ๅฆ‚ๆžœๅฝ“ๅ‰ๆ˜ฏ็ฉบๆ ‘ๅˆ™็ซ‹ๅณ่ฟ”ๅ›ž

  3. ๅฆๅˆ™ๅ…ˆๆ‰พๅˆฐ่ฆๅˆ ้™ค็š„keyๆ‰€ๅœจ็š„page

  4. ้šๅŽ่ฐƒ็”จRemoveAndDeleteRecordๅœจๅถpageไธŠ็›ดๆŽฅๅˆ ้™คkeyๅ€ผ

INDEX_TEMPLATE_ARGUMENTS
void BPLUSTREE_TYPE::Remove(const KeyType &key, Transaction *transaction) {
  {
    // ่ฟ™ไธชไธ“้—จ้’ˆๅฏนไบŽ้žๅนถๅ‘็š„delete
    Page *page = FindLeafPage(key, false);
    LeafPage *leafPage = reinterpret_cast<LeafPage*>(page->GetData()); //pined leafPage

    leafPage->RemoveAndDeleteRecord(key,comparator_);
  1. RemoveAndDeleteRecordๅ‡ฝๆ•ฐ

  2. ่ฟ™้‡Œๅฎž็Žฐ่ถŠๆฅ่ถŠๅƒLeveldbๆ˜ฏๆ€Žไนˆๅ›žไบ‹ใ€‚ใ€‚

  3. ๅˆฉ็”จKeyIndexๅ‡ฝๆ•ฐๅฎž็Žฐ็œŸ็š„็ฎ€ๅ•ใ€‚

INDEX_TEMPLATE_ARGUMENTS
int B_PLUS_TREE_LEAF_PAGE_TYPE::RemoveAndDeleteRecord(const KeyType &key, const KeyComparator &comparator) {
  int pos = KeyIndex(key, comparator);
  if (pos < GetSize() && comparator(array_[pos].first, key) == 0) {
    for (int j = pos + 1; j < GetSize(); j++) {
      array_[j - 1] = array_[j];
    }
    IncreaseSize(-1);
  }
  return GetSize();
}

ไน‹ๅŽๅฐฑๆ˜ฏๅฏนไบŽๅˆ ้™ค็š„ๅค„็†๏ผŒไธป่ฆๆœ‰ไธคไธชไธ€ไธชๆ˜ฏๅˆๅนถ๏ผŒไธ€ไธชๅฐฑๆ˜ฏredistributeใ€‚ๅ…ทไฝ“ๆต็จ‹่งไธ‹

2.2 Coalesceๅฎž็Žฐๆต็จ‹

ๅถๅญ็ป“็‚นๅ†…ๅ…ณ้”ฎๅญ—ไธชๆ•ฐๅฐไบŽๆœ€ๅฐๅ€ผๅ‘ไธ‹ๆ‰ง่กŒใ€‚่ฐƒ็”จๅˆ ้™ค็š„ๆ ธๅฟƒๅ‡ฝๆ•ฐCoalesceAndRedistribute

ไธ‹้ขๆ˜ฏCoalesceAndRedistribute็š„้€ป่พ‘

1.ๅฆ‚ๆžœๅฝ“ๅ‰็ป“็‚นๆ˜ฏๆ น่Š‚็‚นๅˆ™่ฐƒ็”จAdjustRoot(node)

่ฟ™้‡Œ็š„ๆ็คบ็ป™ไบ†ๅ…ถๅฎž่ฟ™ไธชๅ‡ฝๆ•ฐๅฐฑ้’ˆๅฏนไธค็งๆƒ…ๅ†ต

  • Case1 : old_root_nodeๆ˜ฏๅ†…้ƒจ็ป“็‚น๏ผŒไธ”ๅคงๅฐไธบ1๏ผŒ่กจ็คบๅ†…้ƒจ็ป“็‚นๅ…ถๅฎžๅทฒ็ปๆฒกๆœ‰keyไบ†ใ€‚ๆ‰€ไปฅ่ฆๆŠŠๅฎƒ็š„ๅญฉๅญๆ›ดๆ–ฐๆˆๆ–ฐ็š„ๆ น่Š‚็‚น

  • Case2 : old_root_nodeๆ˜ฏๅถๅญ็ป“็‚นใ€‚ไธ”ๅคงๅฐไธบ0๏ผŒ็›ดๆŽฅๅˆ ไบ†ๅฐฑๅฅฝใ€‚

ๅฆๅˆ™ไธ้œ€่ฆๆœ‰page่ขซๅˆ ้™ค๏ผŒๅˆ™็›ดๆŽฅreturn flase

INDEX_TEMPLATE_ARGUMENTS
bool BPLUSTREE_TYPE::AdjustRoot(BPlusTreePage *old_root_node) {
  // case 1 old_root_node (internal node) has only one size
  if (!old_root_node->IsLeafPage() && old_root_node->GetSize() == 1) {
    InternalPage *old_root_page = reinterpret_cast<InternalPage *>(old_root_node);
    page_id_t new_root_page_id = old_root_page->adjustRootForInternal();
    root_page_id_ = new_root_page_id;
    UpdateRootPageId(0);

    Page *new_root_page = buffer_pool_manager_->FetchPage(new_root_page_id);
    BPlusTreePage *new_root = reinterpret_cast<BPlusTreePage *>(new_root_page->GetData());
    new_root->SetParentPageId(INVALID_PAGE_ID);
    buffer_pool_manager_->UnpinPage(new_root_page_id, true);

    return true;
  }
  // case 2 : all elements deleted from the B+ tree
  if (old_root_node->IsLeafPage() && old_root_node->GetSize() == 0) {
    root_page_id_ = INVALID_PAGE_ID;
    UpdateRootPageId(0);
    return true;
  }
  return false;
}

2.ๅฆๅˆ™ๅ…ˆๅˆคๆ–ญๆ˜ฏๅฆ่ฆ่ฟ›่กŒCoalesce

่ฟ™้‡Œ่ฆๆ‰พๅ…„ๅผŸ็ป“็‚น่ฟ›่กŒๅˆๅนถ๏ผŒๅฆ‚ๆžœๆปก่ถณๅˆๅนถ่ฆๆฑ‚็š„่ฏ

1. ๅˆคๆ–ญๆ˜ฏๅฆๆปก่ถณๅˆๅนถ่ฆๆฑ‚

่ฟ™้‡Œๅˆฉ็”จไธ€ไธช่พ…ๅŠฉๅ‡ฝๆ•ฐ่ฟ›่กŒๅˆคๆ–ญใ€‚ๅฆ‚ๆžœไธ่ถ…่ฟ‡ๆœ€ๅคงsizeๅฐฑๅฏไปฅๅˆๅนถ

INDEX_TEMPLATE_ARGUMENTS
template <typename N>
bool BPLUSTREE_TYPE::IsCoalesce(N *nodeL, N *nodeR) {
  // maxSize consider InternalPage and LeafPage
  return nodeL->GetSize() + nodeR->GetSize() <= maxSize(nodeL);
}

โš ๏ธ ๅˆๅนถๅ‡ฝๆ•ฐๆ˜ฏๅ’Œ็›ดๆŽฅๅ‰้ฉฑ่ฟ›่กŒๅˆๅนถ๏ผŒไนŸๅฐฑๆ˜ฏๅ’Œๅฎƒๅทฆ่พน็š„node่ฟ›่กŒๅˆๅนถ

2. ๅˆคๆ–ญๅทฆ่พน็š„pageๆ˜ฏๅฆ่ƒฝ่ฟ›่กŒๅˆๅนถ

  // firstly find from left
    if (left_sib_index >= 0) {
      page_id_t sibling_pid = parent->ValueAt(left_sib_index);
      Page *sibling_page = buffer_pool_manager_->FetchPage(sibling_pid);  // pined sibling_page
      N *sib_node = reinterpret_cast<N *>(sibling_page->GetData());
      if (IsCoalesce(node, sib_node)) {
        // coalesce
        // unpin node and deleted node
        bool del_parent = Coalesce(&sib_node, &node, &parent, cur_index, transaction);
         // unpin sibling page
        buffer_pool_manager_->UnpinPage(sibling_pid, true);     
        // unpin parent page;
        buffer_pool_manager_->UnpinPage(parent_pid, true);                             
        if (del_parent) {
          buffer_pool_manager_->DeletePage(parent_pid);
        }
        return false;  // node is merged into sib, and already deleted
      }
      buffer_pool_manager_->UnpinPage(sibling_pid, false);  // unpin sibling page
    }

3. ๅฆๅˆ™ๅˆคๆ–ญๅณ่พนๆ˜ฏๅฆ่ƒฝ่ฟ›่กŒๅˆๅนถ

// secondly find from right

    if (right_sib_index < parent->GetSize()) {
      page_id_t sibling_pid = parent->ValueAt(right_sib_index);
      Page *sibling_page = buffer_pool_manager_->FetchPage(sibling_pid);  // pined sibling_page
      N *sib_node = reinterpret_cast<N *>(sibling_page->GetData());
      if (IsCoalesce(node, sib_node)) {
        // coalesce
        // unpin right sib and deleted right sib
        bool del_parent =
            Coalesce(&node, &sib_node, &parent, cur_index, transaction);  
        buffer_pool_manager_->UnpinPage(node->GetPageId(), true);         // unpin sibling page
        buffer_pool_manager_->UnpinPage(parent_pid, true);                // unpin parent page;
        if (del_parent) {
          buffer_pool_manager_->DeletePage(parent_pid);
        }
        return false;  // node is merged into sib, and already deleted
      }
      buffer_pool_manager_->UnpinPage(sibling_pid, false);  // unpin sibling page
    }

4. Coaleceๅ‡ฝๆ•ฐ็š„ๅฎž็Žฐ

ๅฎž็Žฐไน‹ๅ‰ๅ…ˆ็œ‹ไธคๅผ ๅ›พ

ๅœจๅˆๅนถไน‹ๅŽ๏ผŒ็ˆถไบฒ็ป“็‚นๅฟ…้กป่ฆๆ›ดๆ–ฐใ€‚ๅ› ไธบ็งปๅŠจๆ“ไฝœๅฏผ่‡ดไบ†ไน‹ๅ‰็ˆถ็ป“็‚น็š„ๆŒ‡้’ˆๅ‘็”Ÿไบ†้”™่ฏฏใ€‚่ฟ™้‡Œไผšๆถ‰ๅŠๅˆฐ็ˆถไบฒ็ป“็‚นๆ˜ฏๅฆ้œ€่ฆๅˆ ้™ค็š„ๆƒ…ๅ†ต

ๅ…ทไฝ“ๆƒ…ๅ†ต่งไธ‹ๅ›พ

img

ๅฏ่ƒฝ็”ฑไบŽๅถๅญ็ป“็‚น็š„ๅˆๅนถๆ“ไฝœ๏ผŒๅฏผ่‡ด็ˆถไบฒ็ป“็‚นๅ˜ๆˆnull็ฉบ็ป“็‚นใ€‚ๆˆ–่€…่ฏดๆ˜ฏๅ…ถไธๆปก่ถณๆœ€ๅฐ็ป“็‚นไธชๆ•ฐ่ฆๆฑ‚ใ€‚่ฟ™ๆ ทๅฐฑ่ฆๅฏน็ˆถไบฒ็ป“็‚น่ฟ›่กŒๅค„็†๏ผŒ่ฟ™ไธชๆ—ถๅ€™ๆ˜ฏ็ˆถไบฒ็ป“็‚นไนŸๅฏไปฅ่ฟ›่กŒๅˆๅนถ๏ผŒ่ฟ™ไธชๆ—ถๅ€™ๅŽŸๆฅ็š„็ˆถไบฒ็ป“็‚นๅฐฑๆ— ไบ†ใ€‚ๅˆๅนถไน‹ๅŽ็š„็ป“ๆžœๅฆ‚ไธ‹ๅ›พ:

img

่ฎฐๅพ—้€’ๅฝ’ๅค„็†ๅฐฑๅฅฝ

INDEX_TEMPLATE_ARGUMENTS
template <typename N>
bool BPLUSTREE_TYPE::Coalesce(N **neighbor_node, N **node, BPlusTreeInternalPage<KeyType, 
                              page_id_t, KeyComparator> **parent, int index, Transaction *transaction) {
  // Assume that *neighbor_node is the left sibling of *node

  // Move entries from node to neighbor_node
  if ((*node)->IsLeafPage()) {
    LeafPage *leaf_node = reinterpret_cast<LeafPage *>(*node);
    LeafPage *leaf_neighbor = reinterpret_cast<LeafPage *>(*neighbor_node);

    leaf_node->MoveAllTo(leaf_neighbor);
    leaf_neighbor->SetNextPageId(leaf_node->GetNextPageId());
  } else {
    InternalPage *internal_node = reinterpret_cast<InternalPage *>(*node);
    InternalPage *internal_neighbor = reinterpret_cast<InternalPage *>(*neighbor_node);

    internal_node->MoveAllTo(internal_neighbor, (*parent)->KeyAt(index), buffer_pool_manager_);
  }

  buffer_pool_manager_->UnpinPage((*node)->GetPageId(), true);
  buffer_pool_manager_->DeletePage((*node)->GetPageId());

  (*parent)->Remove(index);

  // If parent is underfull, recursive operation
  if ((*parent)->GetSize() < minSize(*parent)) {
    return CoalesceOrRedistribute(*parent, transaction);
  }
  return false;
}

5. ๅถๅญ็ป“็‚นๅ’Œๅ†…้ƒจ็ป“็‚นๅฏนๅบ”็š„ไธคไธชMoveAllToๅ‡ฝๆ•ฐ

่ฟ™ไธชๅ‡ฝๆ•ฐๅฐฑไธๅ†™ไบ†ใ€‚ๅฎž็Žฐๆฏ”่พƒ็ฎ€ๅ•๏ผŒๅ”ฏไธ€่ฆๆณจๆ„็š„ๅฐฑๆ˜ฏๅฏนไบŽๅ†…้ƒจ็ป“็‚น็š„ๅˆๅนถๆ“ไฝœ๏ผŒ่ฆๆŠŠ้œ€่ฆๅˆ ้™ค็š„ๅ†…้ƒจ็ป“็‚น็š„ๅถๅญ็ป“็‚น่ฝฌ็งป่ฟ‡ๅŽปใ€‚ไนŸๅฐฑๆ˜ฏ่ฆๆœ‰ไธ‹้ข่ฟ™ๆ ท็š„ไธ€่กŒ

recipient->array_[recipient->GetSize()].first = middle_key;

3. Redistributeๆต็จ‹

ๅฝ“็„ถไนŸๅฏไปฅๅ…ˆ็œ‹ไธ€ไธ‹็ฎ—ๆณ•็คบๆ„ๅ›พใ€‚

ไธ‹ๅ›พๆ˜ฏๅฏนๅถๅญ็ป“็‚น็š„็š„Redistributeๅ‡ฝๆ•ฐ

img

่ฟ™้‡Œๅœจ็งปๅŠจ็š„ๆ—ถๅ€™ๅช่ฆ่ฎฐๅพ—ๆ›ดๆ–ฐ็ˆถไบฒๅฏนๅบ”index็š„keyๅ€ผๅฐฑๅฅฝไบ†ใ€‚

็„ถ่€ŒๅฏนไบŽๅ†…้ƒจ็ป“็‚นๅˆ™ๅนถไธๆ˜ฏ่ฟ™ไนˆ็ฎ€ๅ•็š„ๆƒ…ๅ†ตไบ†ใ€‚ๅ†…้ƒจ็ป“็‚นๅฏไปฅ็›ดๆŽฅไปŽๅฎƒ็š„ๅ…„ๅผŸ็ป“็‚นcopy็„ถๅŽไฟฎๆ”นๅ…ถๆ น่Š‚็‚นๅ—๏ผŒ่ฟ™ๆ˜พ็„ถไธๅˆ็†ใ€‚

ๅฏนไบŽ่ฟ™็งๆƒ…ๅ†ต็š„ๅค„็†ๅฏไปฅ่งไธ‹ๅ›พ

img
img
img
img

ๅ› ๆญคๆ•ดไธชredistributeๆ‰€ๆถ‰ๅŠ็š„ๅ››็งๆƒ…ๅ†ตๅฐฑๅฆ‚ไธ‹

  1. ๅ‘ๅถๅญ็ป“็‚นๅทฆ่พนๅ€Ÿ

  2. ๅ‘ๅถๅญ็ป“็‚นๅณ่พนๅ€Ÿ

  3. ๅ†…้ƒจ็ป“็‚นๅทฆ่พนๅ€Ÿ

  4. ๅ†…้ƒจ็ป“็‚นๅณ่พนๅ€Ÿ

1. ๅฏนไบŽๅถๅญ็ป“็‚นๅ‘ๅทฆ่พนๅ€Ÿ็š„ๆƒ…ๅ†ต

ๅฅฝไบ†ๅˆ ้™ค็ฎ—ๆณ•ๅทฒ็ปๅฎž็Žฐไบ†ใ€‚้ฆ–ๅ…ˆๆˆ‘ไปฌๅฏไปฅ้€š่ฟ‡testๅ‡ฝๆ•ฐ

cd build
make b_plus_tree_delete_test
./test/b_plus_tree_delete_test --gtest_also_run_disabled_tests
image-20210126134731557

็„ถๅŽๆˆ‘ไปฌ่‡ชๅทฑๅšไธ€ไบ›testใ€‚่ฟ™้‡Œๆˆ‘ๅฐฑๆ‹ฟไธ€ไธชไพ‹ๅญๆฅ็œ‹

ๆ’ๅ…ฅ10ใ€5ใ€7ใ€4ใ€9ๅพ—ๅˆฐไธ‹ๅ›พๆ˜ฏๆญฃ็กฎ็š„๐ŸŒŸ

image-20210126134908455

็„ถๅŽๅˆ ้™คๅ…ƒ็ด 7

image-20210126134952965

ๅฏไปฅๅ‘็Žฐๆ˜ฏๅฎŒๅ…จๆญฃ็กฎ็š„ๅฅฝไบ†ใ€‚็ฌฌไบŒ้ƒจๅˆ†ๅฐฑๅฎŒๆˆไบ†ใ€‚ไธ‹้ขๅฐฑๆ˜ฏๆœ€ๅŽไธ€้ƒจๅˆ†ๅฏนไบŽ๐Ÿ”’็š„ๅฎž็Žฐๅ’Œ่ฟญไปฃๅ™จ็š„ๅฎž็Žฐ

Last updated