auto cur_result = current_table->iters_monotony_predicate(predicate); if (cur_result.has_value()) { auto [begin, end] = cur_result.value(); for (auto iter = begin; iter != end; ++iter) { item_vec.emplace_back(iter.get_key(), iter.get_value(), 0); } }
int table_idx = 1; for (auto ft = frozen_tables.begin(); ft != frozen_tables.end(); ft++) { auto table = *ft; auto result = table->iters_monotony_predicate(predicate); if (result.has_value()) { auto [begin, end] = result.value(); for (auto iter = begin; iter != end; ++iter) { item_vec.emplace_back(iter.get_key(), iter.get_value(), table_idx); } } table_idx++; }
if (item_vec.empty()) { return std::nullopt; } return std::make_pair(HeapIterator(item_vec), HeapIterator{}); }
// 第一次二分查找,找到第一个满足谓词的位置 int left = 0; int right = offsets.size() - 1; int first = -1; int first_first = -1; // 第一次找到的位置, 不一定是区间的首尾
while (left <= right) { int mid = left + (right - left) / 2; size_t mid_offset = offsets[mid];
auto mid_key = get_key_at(mid_offset); int direction = predicate(mid_key); if (direction < 0) { // 目标在 mid 左侧 right = mid - 1; } elseif (direction > 0) { // 目标在 mid 右侧 left = mid + 1; } else { first = mid; if (first_first == -1) { first_first = mid; } // 继续判断左边是否符合 right = mid - 1; } }
if (first == -1) { return std::nullopt; // 没有找到满足谓词的元素 }
// 第二次二分查找,找到最后一个满足谓词的位置 left = first_first; right = offsets.size() - 1; int last = -1;
while (left <= right) { int mid = left + (right - left) / 2; size_t mid_offset = offsets[mid];
auto mid_key = get_key_at(mid_offset); int direction = predicate(mid_key);
if (direction < 0) { // 目标在 mid 左侧 right = mid - 1; } elseif (direction > 0) { // 目标在 mid 右侧 throw std::runtime_error("block is not sorted"); } else { last = mid; // 继续判断右边是否符合 left = mid + 1; } }
auto it_begin = std::make_shared<BlockIterator>(shared_from_this(), first); auto it_end = std::make_shared<BlockIterator>(shared_from_this(), last + 1);
// 先从 memtable 中查询 auto mem_result = memtable.iters_monotony_predicate(predicate);
// 再从 sst 中查询 std::vector<SearchItem> item_vec; for (auto &[sst_idx, sst] : ssts) { auto result = sst_iters_monotony_predicate(sst, predicate); if (!result.has_value()) { continue; } auto [it_begin, it_end] = result.value(); for (; it_begin != it_end && it_begin.is_valid(); ++it_begin) { // 这里越古老的sst的idx越小, 我们需要让新的sst优先在堆顶 // 让新的sst(拥有更大的idx)排序在前面, 反转符号就行了 item_vec.emplace_back(it_begin.key(), it_begin.value(), -sst_idx); } }
HeapIterator l0_iter(item_vec);
if (!mem_result.has_value() && item_vec.empty()) { return std::nullopt; } if (mem_result.has_value()) { auto [mem_start, mem_end] = mem_result.value(); auto start = MergeIterator(mem_start, l0_iter); auto end = MergeIterator{}; return std::make_optional<std::pair<MergeIterator, MergeIterator>>(start, end); } else { auto start = MergeIterator(HeapIterator{}, l0_iter); auto end = MergeIterator{}; return std::make_optional<std::pair<MergeIterator, MergeIterator>>(start, end); } }
3 范围查询/前缀查询
现在我们可以借助我们的谓词查询来完成前缀查询和范围查询了:
3.1 范围查询
这里返回值是目标位置相对当前位置的方向:
如果当前位置更大, 则目标位于左边, 返回-1 (返回小于0的值都可以)
如果当前位置更小, 则目标位于右边, 返回1 (返回大于0的值都可以)
如果当前位置等于目标, 则返回0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
LSM lsm(test_dir);
auto predicate = [](const std::string &key) -> int { int key_num = std::stoi(key.substr(3)); // Extract the number from the key if (key_num < 20) { return1; } if (key_num > 60) { return-1; } return0; };
// Call the method under test auto result = lsm.lsm_iters_monotony_predicate(predicate);