fix: add case for update till root
This commit is contained in:
@ -410,6 +410,17 @@ class BPlusTreeIndexer {
|
||||
RemoveEntryInRightSkewPath(pos);
|
||||
return;
|
||||
}
|
||||
void TryUpdateTillRoot(PositionSignType &pos) {
|
||||
if (pos.path.size() < 2) return;
|
||||
BasicPageGuard &page_guard = pos.path.back().first;
|
||||
if (pos.path.back().second != page_guard.template As<PageType>()->data.key_count - 1) return;
|
||||
BasicPageGuard &parent_page_guard = pos.path[pos.path.size() - 2].first;
|
||||
if (pos.path[pos.path.size() - 2].second >= parent_page_guard.template As<PageType>()->data.key_count) return;
|
||||
parent_page_guard.template AsMut<PageType>()->data.p_data[pos.path[pos.path.size() - 2].second].first =
|
||||
page_guard.template As<PageType>()->data.p_data[page_guard.template As<PageType>()->data.key_count - 1].first;
|
||||
pos.path.pop_back();
|
||||
TryUpdateTillRoot(pos);
|
||||
}
|
||||
void RemoveEntryAt(PositionSignType &pos, bool is_fixing_up_recursive = false) {
|
||||
if (siz == 1) {
|
||||
// special case for the last entry
|
||||
@ -429,10 +440,16 @@ class BPlusTreeIndexer {
|
||||
page_guard.template As<PageType>()->data.p_data + pos.path.back().second + 1,
|
||||
(page_guard.template As<PageType>()->data.key_count - pos.path.back().second - 1) * sizeof(key_index_pair_t));
|
||||
page_guard.template AsMut<PageType>()->data.key_count--;
|
||||
bool need_update = false;
|
||||
if (pos.path.size() >= 2 && page_guard.template AsMut<PageType>()->data.key_count == pos.path.back().second) {
|
||||
auto &parent_page_guard = pos.path[pos.path.size() - 2].first;
|
||||
parent_page_guard.template AsMut<PageType>()->data.p_data[pos.path[pos.path.size() - 2].second].first =
|
||||
page_guard.template As<PageType>()->data.p_data[page_guard.template As<PageType>()->data.key_count - 1].first;
|
||||
if (pos.path[pos.path.size() - 2].second < parent_page_guard.template As<PageType>()->data.key_count) {
|
||||
parent_page_guard.template AsMut<PageType>()->data.p_data[pos.path[pos.path.size() - 2].second].first =
|
||||
page_guard.template As<PageType>()
|
||||
->data.p_data[page_guard.template As<PageType>()->data.key_count - 1]
|
||||
.first;
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
if (has_enough_keys) {
|
||||
if (page_guard.template As<PageType>()->data.page_status & PageStatusType::ROOT &&
|
||||
@ -444,7 +461,11 @@ class BPlusTreeIndexer {
|
||||
page_id_t page_to_delete = page_guard.PageId();
|
||||
pos.path.clear(); // all page_guards are invalid now
|
||||
bpm->DeletePage(page_to_delete);
|
||||
return;
|
||||
}
|
||||
if (need_update) {
|
||||
// now we need to check if we have to update the right bound till the root
|
||||
pos.path.pop_back();
|
||||
TryUpdateTillRoot(pos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
- p[i]子树中的所有key K都满足: k[i-1] \< K \<= k[i],且k[i]一定能取到,即直接无缝对接lower_bound
|
||||
- 对外接口提供类似于迭代器的东西,但该迭代器只支持向后单项移动、读取value值、修改value值,并且,迭代器会保留PageGuard,因此如果B+树在迭代器之前析构,会出现访问越界。
|
||||
- 由于子区间**左开右闭**,于是绝大多数Internal Page和Leaf Page一样,都没有尾后指针,整棵树的左下角会有一大片的leaf like pages,它们都有个共同特性,即指针数量和键值数量相同,但真正的leaf page还需要额外维护page状态标号和p_n指针。
|
||||
- 当删除时,有一定可能在leaf like区域触发一路更新到树根的操作
|
||||
|
||||
# UI设计
|
||||
- 语言:Python
|
||||
|
@ -21,8 +21,8 @@ int main(int argc, char *argv[]) {
|
||||
fprintf(fout, "Seed = %u\n", RndSeed);
|
||||
fclose(fout);
|
||||
// ======================================
|
||||
int n = 1000;
|
||||
int total_keys = 300;
|
||||
int n = 100000;
|
||||
int total_keys = 30000;
|
||||
set<string> keys_set;
|
||||
for (int i = 0; i < total_keys; i++) {
|
||||
string key = "#" + to_string(rnd_less(1000000)) + "#";
|
||||
@ -36,7 +36,7 @@ int main(int argc, char *argv[]) {
|
||||
cout << n << endl;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int tmp = rnd() % 10;
|
||||
if (tmp <= 4) {
|
||||
if (tmp <= 3) {
|
||||
string key = keys_vec[rnd_less(keys_vec.size())];
|
||||
int val = rnd_less(1000000);
|
||||
cout << "insert " << key << " " << val << "\n";
|
||||
@ -46,7 +46,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (tmp <= 6) {
|
||||
string key = keys_vec[rnd_less(keys_vec.size())];
|
||||
int val = rnd_less(1000000);
|
||||
if (rnd() % 2 == 0 && mp[key].size() > 0) {
|
||||
if (rnd() % 4 > 0 && mp[key].size() > 0) {
|
||||
// 选择一个有意义的删除项
|
||||
val = mp[key][rnd_less(mp[key].size())];
|
||||
}
|
||||
|
Reference in New Issue
Block a user