๐Ÿ˜‰B+ Tree Index

PROJECT #2 - B+TREE

็ดขๅผ•่ดŸ่ดฃๅฟซ้€Ÿๅœฐๆฃ€็ดขๆ•ฐๆฎ๏ผŒ่€Œไธ้œ€่ฆๆœ็ดขๆ•ฐๆฎๅบ“่กจไธญ็š„ๆฏไธ€่กŒ๏ผ›็ดขๅผ•่ฟ˜ๆไพ›ไบ†ๅฟซ้€Ÿ็š„้šๆœบ่ฎฟ้—ฎไปฅๅŠ้ซ˜ๆ•ˆๅœฐ่ฎฟ้—ฎๆœ‰ๅบ่ฎฐๅฝ•ใ€‚ๅ› ๆญค๏ผŒๅœจ่ฟ™ไธช็ผ–็จ‹ไฝœไธšไธญ๏ผŒๆˆ‘ไปฌ้œ€่ฆๅฎž็ŽฐๅŸบไบŽ B+ ๆ ‘็š„ๅŠจๆ€็ดขๅผ•็ป“ๆž„ใ€‚

CHECKPOINT #1

TASK #1 - B+TREE PAGES

ๅฎž็Žฐไธ‰ไธช Page ็ฑปๆฅๅญ˜ๅ‚จ B+ ๆ ‘็š„ๆ•ฐๆฎ

  • B+Tree Parent Page

  • B+Tree Internal Page

  • B+Tree Leaf Page

b_plus_tree_page.cpp ็š„ๅฎž็Žฐ

็›ดๆŽฅๆ นๆฎๅ‡ฝๆ•ฐ่ฆๆฑ‚่ฎพ็ฝฎๆˆ–่ฟ”ๅ›žๅฏนๅบ”็š„ๅญ—ๆฎตๅณๅฏใ€‚

  • IsRootPage ๅ‡ฝๆ•ฐๆ นๆฎ parent_id_ ๆ˜ฏๅฆๆ˜ฏ INVALID_PAGE_ID ่ฟ”ๅ›ž true ๆˆ–่€… false

  • GetMinSize()๏ผš้œ€่ฆๅŒบๅˆ† 1๏ผ‰ๆ น็ป“็‚นไธ”ไธบๅถๅญ็ป“็‚นใ€‚2๏ผ‰ๆ น็ป“็‚นใ€‚3๏ผ‰ๅ…ถไป–

b_plus_tree_internal_page.cpp ็š„ๅฎž็Žฐ

  • MappingType ็š„็ฑปๅž‹ไธบ std::pair<KeyType, ValueType>๏ผŒๅฆ‚ไฝ•่Žทๅ–็ฌฌ i ไธช MappingType๏ผŸ=> ๅœจๅ…ถๅคดๆ–‡ไปถๆœ‰ไธ€ไธช array ็š„ MappingType ๆ•ฐ็ป„๏ผˆarray[0] ่กจ็คบ่ฟ™ๆ˜ฏไธ€ไธชๅผนๆ€งๆ•ฐ็ป„๏ผ‰

  • ๆณจๆ„ๆœ‰ไบ›ๅ‡ฝๆ•ฐ้œ€่ฆๅˆคๆ–ญ index ๆ˜ฏๅฆๅˆๆณ•๏ผŒไฝฟ็”จ assert()

  • ๅฐ† bpm ๅ–ๅ‡บ็š„้กต้ข่ฝฌๆขไธบ internal page/leaf page๏ผˆ้‡่ฆ๏ผ‰

b_plus_tree_internal_page.cpp
Page *page = buffer_pool_manager_->FetchPage(page_id);
assert(page != nullptr);
// ๅฐ† page ่ฝฌๆˆ BPlusTreeInternalPage ็ฑป
BPlusTreeInternalPage *bpt_node = reinterpret_cast<BPlusTreeInternalPage *>(page->GetData());
// do something
buffer_pool_manager_->UnpinPage(bpt_node->GetPageId(), flag); // ๆ˜ฏๅฆไฟฎๆ”นไบ†้กต้ข๏ผŒflag ไธบ true ๆˆ–่€… false
  • Helper method

// ่ฟ”ๅ›ž index ่ฟ™ไธชไฝ็ฝฎ็š„ Key
KeyType KeyAt(int index) const;
// ่ฎพ็ฝฎ index ่ฟ™ไธชไฝ็ฝฎ็š„ Key = key
void SetKeyAt(int index, const KeyType &key);
// ่ฟ”ๅ›ž array ไธญ Value == value ็š„ไธ‹ๆ ‡
int ValueIndex(const ValueType &value) const;
// ่ฟ”ๅ›ž index ่ฟ™ไธชไฝ็ฝฎ็š„ Value
ValueType ValueAt(int index) const;
  • Lookup

/**
 * ไฝฟ็”จไบŒๅˆ†ๆœ็ดขๆ‰พๅˆฐ็ฌฌไธ€ไธชๅคงไบŽ็ญ‰ไบŽ key ็š„ไธ‹ๆ ‡๏ผŒๆณจๆ„ๅทฆๅŒบ้—ดไปŽ 1 ๅผ€ๅง‹
 */
ValueType Lookup(const KeyType &key, const KeyComparator &comparator) const;
  • Insertion

/**
 * ๅฝ“ๆ’ๅ…ฅๅฏผ่‡ดไปŽ leaf page ๅˆฐ root page ๆบขๅ‡บๆ—ถ๏ผŒๆˆ‘ไปฌๅบ”่ฏฅๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ root page๏ผŒ็„ถๅŽๅˆๅง‹ๅŒ–ๅฎƒ
 * array[0].first = old_value
 * ๆณจ๏ผš่ฟ™ไธชๆ–นๆณ•ๅช่ƒฝ็”ฑ InsertIntoParent() ่ฐƒ็”จ(b_plus_tree.cpp)
 */
void PopulateNewRoot(const ValueType &old_value, const KeyType &new_key, const ValueType &new_value);
/**
 * ๅœจ old_value ไฝ็ฝฎไน‹ๅŽๆ’ๅ…ฅไธ€ไธช <Key, Value>
 * ๆณจ๏ผšๅฏไปฅไฝฟ็”จ ValueIndex ๆฅๆ‰พๅˆฐ old_value ็š„ไธ‹ๆ ‡๏ผ›ๆ’ๅ…ฅๅŽๅˆซๅฟ˜ไบ†ๆ›ดๆ–ฐ size_
 */
int InsertNodeAfter(const ValueType &old_value, const KeyType &new_key, const ValueType &new_value);
  • Remove

/**
 * ๅˆ ้™ค array[index] ่ฟ™ไธชๅ…ƒ็ด ๏ผˆๅŽ้ข็š„ๅ…ƒ็ด ๅ‘ๅ‰็งปไธ€ไฝ๏ผ‰
 * ๆณจ๏ผšๅˆ ้™คๅ…ƒ็ด ๅŽๅˆซๅฟ˜ไบ†ๆ›ดๆ–ฐ size_
 */
void Remove(int index);
/**
 * ๅˆ ้™ค internal page ไธญ็š„ๅ”ฏไธ€ไธ€ไธชๅ…ƒ็ด ๏ผŒๅนถ่ฟ”ๅ›žๅฎƒ็š„ value
 */
ValueType RemoveAndReturnOnlyChild();
  • Split and Merge utility methods

/**
 * Split: ็”ฑไบŽๆ’ๅ…ฅไธ€ไธช <K, V> ๅฏผ่‡ด page full๏ผŒๅ› ๆญคๅฐ†่ฟ™ไธ€้กตไธ€ๅŠ็š„ <K, V> ็งปๅˆฐ "recipient" ้กต
 */
void MoveHalfTo(BPlusTreeInternalPage *recipient, BufferPoolManager *buffer_pool_manager);

// ่พ…ๅŠฉๅ‡ฝๆ•ฐ๏ผŒๆ‰ง่กŒ <K, V> ๆ‹ท่ดๆ“ไฝœ๏ผŒๅŒๆ—ถๆ›ดๆ–ฐ่ฟ™ไบ›่ขซ็งปๅŠจ่Š‚็‚น็š„ parent_page_id
void CopyNFrom(MappingType *items, int size, BufferPoolManager *buffer_pool_manager);

/**
 * Merge: ๅฐ†่ฏฅ้กต็š„ๆ‰€ๆœ‰ <K, V> ็งปๅˆฐ "recipient" ้กต
 */
void MoveAllTo(BPlusTreeInternalPage *recipient, const KeyType &middle_key, BufferPoolManager *buffer_pool_manager);

/****** Redistribute ******/
/**
 * ๅ€Ÿๅฝ“ๅ‰้กต็š„็ฌฌไธ€ไธชๆœ‰ๆ•ˆ็š„ <K, V>
 * ๅฐ† <middle_key, ValueAt(0)> ็งปๅˆฐ "recipient" page ็š„ๆœ€ๅŽไธ€ไธช slot
 * ็„ถๅŽๆ›ดๆ–ฐ parent page ็š„ middl_key
 */
void MoveFirstToEndOf(BPlusTreeInternalPage *recipient, const KeyType &middle_key,
                    BufferPoolManager *buffer_pool_manager);
/**
 * ๅฐ† pair ๆทปๅŠ ๅˆฐ array ๆœซๅฐพ๏ผŒ็„ถๅŽๆ›ดๆ–ฐ่ฟ™ไธช entry ็š„ parent page id
 */
void CopyLastFrom(const MappingType &pair, BufferPoolManager *buffer_pool_manager);
/**
 * ๅ€Ÿๅฝ“ๅ‰้กต็š„ๆœ€ๅŽไธ€ไธชๆœ‰ๆ•ˆ็š„ <K, V>
 * ๅฐ† <middle_key, ValueAt(size - 1)> ็งปๅˆฐ "recipient" page ็š„็ฌฌไธ€ไธช slot
 * ็„ถๅŽๆ›ดๆ–ฐ parent page ็š„ middl_key
 */
void MoveLastToFrontOf(BPlusTreeInternalPage *recipient, const KeyType &middle_key,
                     BufferPoolManager *buffer_pool_manager);
/**
 * ๅฐ† pair ๆทปๅŠ ๅˆฐ array ็š„็ฌฌไธ€ไธชๆœ‰ๆ•ˆไฝ็ฝฎ๏ผŒ็„ถๅŽๆ›ดๆ–ฐ่ฟ™ไธช entry ็š„ parent page id
 */
void CopyFirstFrom(const MappingType &pair, BufferPoolManager *buffer_pool_manager);

ๆณจ๏ผšMerge ๅ’Œ Redistribute ็š„ๅ‡ ไธชๅ‡ฝๆ•ฐๅฏไปฅๆ”พๅœจ CP2 ไธญๅฎŒๆˆ

b_plus_tree_Leaf_page.cpp ็š„ๅฎž็Žฐ

  • Helper method

// ่ฟ”ๅ›žๅฝ“ๅ‰ page ็š„ไธ‹ไธ€ไธช page ็š„ page id
page_id_t GetNextPageId() const;
// ่ฎพ็ฝฎ next_page_id
void SetNextPageId(page_id_t next_page_id);
// ่ฟ”ๅ›ž array[index] ไฝ็ฝฎ็š„ Key
KeyType KeyAt(int index) const;
// ่ฟ”ๅ›ž array ไธญ็ฌฌไธ€ไธชๅคงไบŽ็ญ‰ไบŽ key ็š„ index
int KeyIndex(const KeyType &key, const KeyComparator &comparator) const;
// ่ฟ”ๅ›ž array[index]
const MappingType &GetItem(int index);
  • Insertionใ€Searchใ€Delete

/**
 * ๅฐ† <key, value> ๆ’ๅ…ฅๅˆฐๅถๅญ่Š‚๏ผŒ่ฟ”ๅ›žๆ’ๅ…ฅๅŽ็š„ page size
 * 1. ๆ‰พๅˆฐ้œ€่ฆๆ’ๅ…ฅๅˆฐไฝ็ฝฎ๏ผŒๅˆคๆ–ญ่ฏฅไฝ็ฝฎ็š„ key ๆ˜ฏๅฆ็ญ‰ไบŽ "key"๏ผŒ็”ฑไบŽๅชๆ”ฏๆŒ unique key๏ผŒๆ‰€ไปฅ็›ธ็ญ‰ๆ—ถ็›ดๆŽฅ่ฟ”ๅ›ž page size
 * 2. ๆ‰ง่กŒๆ’ๅ…ฅๆ“ไฝœ
 * 3. ๆ›ดๆ–ฐ size_
 */
int Insert(const KeyType &key, const ValueType &value, const KeyComparator &comparator);
/**
 * ๆŸฅๆ‰พ key ๆ˜ฏๅฆๅœจๅถๅญ่Š‚็‚นไธญใ€‚ๅฆ‚ๆžœๅœจ๏ผŒๅฐ† key ๅฏนๅบ”็š„ Value ๅญ˜ๅœจ "value" ไธญ๏ผŒ่ฟ”ๅ›ž true๏ผ›ๅฆๅˆ™่ฟ”ๅ›ž false
 */
bool Lookup(const KeyType &key, ValueType *value, const KeyComparator &comparator) const;
/**
 * ๅœจๅถๅญ่Š‚็‚นไธญๅˆ ้™ค key
 * ๅฆ‚ๆžœ key ไธๅญ˜ๅœจ๏ผŒ็›ดๆŽฅ่ฟ”ๅ›ž page size
 * ๅฆๅˆ™ๅˆ ้™ค่ฟ™ไธช key๏ผŒๆ›ดๆ–ฐ size_๏ผŒ่ฟ”ๅ›ž page size
 */
int RemoveAndDeleteRecord(const KeyType &key, const KeyComparator &comparator);
  • Split and Merge utility methods

// ็ฑปไผผไบŽ BPlusTreeInternalPage ็š„ๅฎž็Žฐ
void MoveHalfTo(BPlusTreeLeafPage *recipient);
void CopyNFrom(MappingType *items, int size);
void MoveAllTo(BPlusTreeLeafPage *recipient);
void MoveFirstToEndOf(BPlusTreeLeafPage *recipient);
void CopyLastFrom(const MappingType &item);
void MoveLastToFrontOf(BPlusTreeLeafPage *recipient);
void CopyFirstFrom(const MappingType &item);

ๅๆงฝ๏ผšไธŠ้ข็š„ๅ››ไธช Move ๅ‡ฝๆ•ฐๅ’Œ BPlusTreeInternalPage ็ฑปไธญ็š„ๅŒๅๅ‡ฝๆ•ฐๅ‚ๆ•ฐไธไธ€่‡ด๏ผŒๅฏผ่‡ดๅŽ้ข Split ไธญ่ฐƒ็”จๆŠฅ้”™ใ€‚ไน‹ๅŽๆˆ‘ๅฐ†่ฟ™ไธ€็ป„ๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐๆ”นไธบไธ€่‡ดๆ‰็ผ–่ฏ‘้€š่ฟ‡ใ€‚


  • FindLeafPage ่ฟ™ไธชๅ‡ฝๆ•ฐๆ˜ฏๆŸฅๆ‰พใ€ๆ’ๅ…ฅใ€ๅˆ ้™คๆ“ไฝœ็š„ๅŸบ็ก€๏ผŒๅฎƒๆ˜ฏๆ‰พๅˆฐ key ๆ‰€ๅœจ็š„ๅถๅญ่Š‚็‚น๏ผŒleftMost = true ๆ—ถ่กจ็คบ่ฟ”ๅ›ž B+ ๆ ‘ไธญๆœ€ๅทฆ่พน็š„ๅถๅญ่Š‚็‚น

  • ๅœจ InsertIntoLeaf ๅ‡ฝๆ•ฐไธญ๏ผŒๅฆ‚ๆžœๆ’ๅ…ฅๅŽ๏ผŒๅถๅญ็ป“็‚นๅŒ…ๅซ็š„ <K, V> ไธชๆ•ฐ็ญ‰ไบŽ GetMaxSize()๏ผŒๆญคๆ—ถๅฐฑ่ฆ่ฟ›่กŒๅˆ†่ฃ‚

  • ๅœจ InsertIntoParent ๅ‡ฝๆ•ฐไธญ๏ผŒๆ’ๅ…ฅๅŽ็š„ไธญ้—ด็ป“็‚นๅŒ…ๅซ็š„ <K, V> ไธชๆ•ฐๅคงไบŽ GetMaxSize() ๆ‰่ฟ›่กŒๅˆ†่ฃ‚


CHECKPOINT #2

TASK #3 - INDEX ITERATOR

่ฟญไปฃๅ™จ็š„ๅฎž็Žฐไธป่ฆๆ˜ฏๆณจๆ„ไป€ไนˆๆ—ถๅ€™็ป“ๆŸ๏ผŸ๏ผˆๅˆฐ่พพๆœ€ๅณ่พนๅถๅญ่Š‚็‚น็š„ๆœ€ๅŽไธ€ไธช slot๏ผ‰ไปฅๅŠๅฎž็Žฐ ++ ๆ“ไฝœๆ—ถ๏ผŒๅค„็†ไธ‹ไธ€ไธชๅถๅญ่Š‚็‚น็š„ๆƒ…ๅ†ตใ€‚


TASK #4 - CONCURRENT INDEX

  • coalesce ๆˆ–่€… redistribute ๆ“ไฝœๆ—ถ้œ€่ฆ่Žทๅพ— sibling ็š„ W Latch

  • ไธบไบ†ไฟๆŠค root_page_id_๏ผŒ้‡‡็”จไบ†่™šๆ‹Ÿ้กต v_root_page๏ผŒๅ’Œไธ€ไธช mutex_

/** 
 * ๅœจ b_plus_tree class ้‡Œๅฎšไน‰ไธ€ไธชๆˆๅ‘˜ๅ˜้‡ Page v_root_page ๅ’Œ std::mutex mutex_
 * ๆฏๆฌก FindLeafPage ็š„ๆ—ถๅ€™ๅ…ˆไฝฟ็”จ mutex_๏ผŒๅ†ๆŠŠ &v_root_page ๅŠ ่ฟ› transaction->page_set_
 * mutex_ ็š„้‡Šๆ”พๅ–ๅ†ณไบŽ root page ๆ˜ฏๅฆๅฎ‰ๅ…จ
 */
  • Crabbing Locking๏ผˆ่งฃ้”้กบๅบๅ’ŒๅŠ ้”้กบๅบ่ฆไธ€่‡ด๏ผ‰

/**
 * 1. ๅฆ‚ๆžœ op = search๏ผŒ้‚ฃไนˆ่Žทๅ–ๅˆฐๅญ่Š‚็‚น็š„ RLatch ๅŽ๏ผŒๅบ”่ฏฅ้‡Šๆ”พไน‹ๅ‰ๆทปๅŠ ๅˆฐ page_set_ ็š„้กต้ข
 * 2. ๅฆ‚ๆžœ op = insert๏ผŒ้‚ฃไนˆ่Žทๅ–ๅˆฐๅญ่Š‚็‚น็š„ WLatch ๅŽ๏ผŒๆฃ€ๆŸฅ่ฏฅ page ๆ˜ฏๅฆๅฎ‰ๅ…จ(size < max_size_)๏ผ›ๆ˜ฏ็š„่ฏ้‡Šๆ”พไน‹ๅ‰ๆ‰€ๆœ‰้กต้ข
 * 3. ๅฆ‚ๆžœ op = delete๏ผŒ้‚ฃไนˆ่Žทๅ–ๅˆฐๅญ่Š‚็‚น็š„ WLatch ๅŽ๏ผŒๆฃ€ๆŸฅ่ฏฅ page ๆ˜ฏๅฆๅฎ‰ๅ…จ(size > min_size_)๏ผ›ๆ˜ฏ็š„่ฏ้‡Šๆ”พไน‹ๅ‰ๆ‰€ๆœ‰้กต้ข
 * ๆœ€ๅŽๆทปๅŠ ่ฏฅ้กตๅˆฐ page_set_
 */
INDEX_TEMPLATE_ARGUMENTS
void BPLUSTREE_TYPE::LockThisPage(int op, Page *page, Transaction *transaction) {}

/**
 * 1. ้‡Šๆ”พ page_set_ ไธญ็š„ R/W Latch
 * 2. ๅˆ ้™คไฟๅญ˜็€ delete_page_set_ ไธญ็š„้กต้ข๏ผŒ็„ถๅŽๆธ…็ฉบ delete_page_set_
 */
INDEX_TEMPLATE_ARGUMENTS
void BPLUSTREE_TYPE::UnlockPrevPage(int op, Transaction *transaction, bool is_dirty) {}

ๆต‹่ฏ•/้ชŒ่ฏ/ๆ‰“ๅŒ…

  • ๆต‹่ฏ•

cd build
make b_plus_tree_insert_test
./test/b_plus_tree_insert_test
make b_plus_tree_delete_test
./test/b_plus_tree_delete_test
make b_plus_tree_concurrent_test
./test/b_plus_tree_concurrent_test
  • ๆ ผๅผ้ชŒ่ฏ

make format
make check-lint
make check-clang-tidy
  • ๆ‰“ๅŒ…

zip project2-submission.zip src/include/buffer/lru_replacer.h src/buffer/lru_replacer.cpp \
	src/include/buffer/buffer_pool_manager.h src/buffer/buffer_pool_manager.cpp \
	src/include/storage/page/b_plus_tree_page.h src/storage/page/b_plus_tree_page.cpp \
	src/include/storage/page/b_plus_tree_internal_page.h src/storage/page/b_plus_tree_internal_page.cpp \
	src/include/storage/page/b_plus_tree_leaf_page.h src/storage/page/b_plus_tree_leaf_page.cpp \
	src/include/storage/index/b_plus_tree.h src/storage/index/b_plus_tree.cpp \
	src/include/storage/index/index_iterator.h src/storage/index/index_iterator.cpp

็„ถๅŽๅ‰ๅพ€ https://www.gradescope.com ๆไบคไปฃ็ 

Last updated