-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CompactRange()
always compacts to bottommost level for leveled compaction
#11468
Changes from all commits
971fb1e
64aa144
136c83e
026a21a
de567b6
707d267
1952285
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1066,7 +1066,6 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options, | |
std::numeric_limits<uint64_t>::max(), trim_ts); | ||
} else { | ||
int first_overlapped_level = kInvalidLevel; | ||
int max_overlapped_level = kInvalidLevel; | ||
{ | ||
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this); | ||
Version* current_version = super_version->current; | ||
|
@@ -1142,10 +1141,8 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options, | |
begin, end); | ||
} | ||
if (overlap) { | ||
if (first_overlapped_level == kInvalidLevel) { | ||
first_overlapped_level = level; | ||
} | ||
max_overlapped_level = level; | ||
first_overlapped_level = level; | ||
break; | ||
} | ||
} | ||
CleanupSuperVersion(super_version); | ||
|
@@ -1159,7 +1156,7 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options, | |
end, exclusive, true /* disallow_trivial_move */, | ||
std::numeric_limits<uint64_t>::max() /* max_file_num_to_ignore */, | ||
trim_ts); | ||
final_output_level = max_overlapped_level; | ||
final_output_level = first_overlapped_level; | ||
} else { | ||
assert(cfd->ioptions()->compaction_style == kCompactionStyleLevel); | ||
uint64_t next_file_number = versions_->current_next_file_number(); | ||
|
@@ -1171,7 +1168,29 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options, | |
int level = first_overlapped_level; | ||
final_output_level = level; | ||
int output_level = 0, base_level = 0; | ||
while (level < max_overlapped_level || level == 0) { | ||
for (;;) { | ||
// Always allow L0 -> L1 compaction | ||
if (level > 0) { | ||
if (cfd->ioptions()->level_compaction_dynamic_level_bytes) { | ||
assert(final_output_level < cfd->ioptions()->num_levels); | ||
if (final_output_level + 1 == cfd->ioptions()->num_levels) { | ||
break; | ||
} | ||
} else { | ||
// TODO(cbi): there is still a race condition here where | ||
// if a background compaction compacts some file beyond | ||
// current()->storage_info()->num_non_empty_levels() right after | ||
// the check here.This should happen very infrequently and should | ||
// not happen once a user populates the last level of the LSM. | ||
InstrumentedMutexLock l(&mutex_); | ||
// num_non_empty_levels may be lower after a compaction, so | ||
// we check for >= here. | ||
if (final_output_level + 1 >= | ||
cfd->current()->storage_info()->num_non_empty_levels()) { | ||
break; | ||
} | ||
} | ||
} | ||
output_level = level + 1; | ||
if (cfd->ioptions()->level_compaction_dynamic_level_bytes && | ||
level == 0) { | ||
|
@@ -1203,28 +1222,20 @@ Status DBImpl::CompactRangeInternal(const CompactRangeOptions& options, | |
if (s.ok()) { | ||
assert(final_output_level > 0); | ||
// bottommost level intra-level compaction | ||
// TODO(cbi): this preserves earlier behavior where if | ||
// max_overlapped_level = 0 and bottommost_level_compaction is | ||
// kIfHaveCompactionFilter, we only do a L0 -> LBase compaction | ||
// and do not do intra-LBase compaction even when user configures | ||
// compaction filter. We may want to still do a LBase -> LBase | ||
// compaction in case there is some file in LBase that did not go | ||
// through L0 -> LBase compaction, and hence did not go through | ||
// compaction filter. | ||
if ((options.bottommost_level_compaction == | ||
BottommostLevelCompaction::kIfHaveCompactionFilter && | ||
max_overlapped_level != 0 && | ||
(cfd->ioptions()->compaction_filter != nullptr || | ||
cfd->ioptions()->compaction_filter_factory != nullptr)) || | ||
options.bottommost_level_compaction == | ||
BottommostLevelCompaction::kForceOptimized || | ||
options.bottommost_level_compaction == | ||
BottommostLevelCompaction::kForce) { | ||
// Use `next_file_number` as `max_file_num_to_ignore` to avoid | ||
// rewriting newly compacted files when it is kForceOptimized. | ||
// rewriting newly compacted files when it is kForceOptimized | ||
// or kIfHaveCompactionFilter with compaction filter set. | ||
s = RunManualCompaction( | ||
cfd, final_output_level, final_output_level, options, begin, | ||
end, exclusive, !trim_ts.empty() /* disallow_trivial_move */, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Intra-level compaction does not allow trivial move anyway. |
||
end, exclusive, true /* disallow_trivial_move */, | ||
next_file_number /* max_file_num_to_ignore */, trim_ts); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2063,6 +2063,7 @@ class PinL0IndexAndFilterBlocksTest | |
ASSERT_OK(Flush(1)); | ||
// move this table to L1 | ||
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, handles_[1])); | ||
ASSERT_EQ(1, NumTableFilesAtLevel(1, 1)); | ||
|
||
// reset block cache | ||
table_options.block_cache = NewLRUCache(64 * 1024); | ||
|
@@ -2220,7 +2221,7 @@ TEST_P(PinL0IndexAndFilterBlocksTest, DisablePrefetchingNonL0IndexAndFilter) { | |
// this should be read from L1 | ||
value = Get(1, "a"); | ||
if (!disallow_preload_) { | ||
// In inifinite max files case, there's a cache miss in executing Get() | ||
// In infinite max files case, there's a cache miss in executing Get() | ||
// because index and filter are not prefetched before. | ||
ASSERT_EQ(fm + 2, TestGetTickerCount(options, BLOCK_CACHE_FILTER_MISS)); | ||
ASSERT_EQ(fh, TestGetTickerCount(options, BLOCK_CACHE_FILTER_HIT)); | ||
|
@@ -2248,12 +2249,12 @@ TEST_P(PinL0IndexAndFilterBlocksTest, DisablePrefetchingNonL0IndexAndFilter) { | |
ASSERT_EQ(fm + 3, TestGetTickerCount(options, BLOCK_CACHE_FILTER_MISS)); | ||
ASSERT_EQ(fh, TestGetTickerCount(options, BLOCK_CACHE_FILTER_HIT)); | ||
ASSERT_EQ(im + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_MISS)); | ||
ASSERT_EQ(ih + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we no longer read more levels to compute max_overlapped_level. Same for the changes below. |
||
ASSERT_EQ(ih + 2, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
} else { | ||
ASSERT_EQ(fm + 3, TestGetTickerCount(options, BLOCK_CACHE_FILTER_MISS)); | ||
ASSERT_EQ(fh + 1, TestGetTickerCount(options, BLOCK_CACHE_FILTER_HIT)); | ||
ASSERT_EQ(im + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_MISS)); | ||
ASSERT_EQ(ih + 4, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
ASSERT_EQ(ih + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
} | ||
|
||
// Bloom and index hit will happen when a Get() happens. | ||
|
@@ -2262,12 +2263,12 @@ TEST_P(PinL0IndexAndFilterBlocksTest, DisablePrefetchingNonL0IndexAndFilter) { | |
ASSERT_EQ(fm + 3, TestGetTickerCount(options, BLOCK_CACHE_FILTER_MISS)); | ||
ASSERT_EQ(fh + 1, TestGetTickerCount(options, BLOCK_CACHE_FILTER_HIT)); | ||
ASSERT_EQ(im + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_MISS)); | ||
ASSERT_EQ(ih + 4, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
ASSERT_EQ(ih + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
} else { | ||
ASSERT_EQ(fm + 3, TestGetTickerCount(options, BLOCK_CACHE_FILTER_MISS)); | ||
ASSERT_EQ(fh + 2, TestGetTickerCount(options, BLOCK_CACHE_FILTER_HIT)); | ||
ASSERT_EQ(im + 3, TestGetTickerCount(options, BLOCK_CACHE_INDEX_MISS)); | ||
ASSERT_EQ(ih + 5, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
ASSERT_EQ(ih + 4, TestGetTickerCount(options, BLOCK_CACHE_INDEX_HIT)); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -286,9 +286,9 @@ TEST_F(ManualCompactionTest, SkipLevel) { | |
filter->Reset(); | ||
ASSERT_OK(db->CompactRange(CompactRangeOptions(), &start, nullptr)); | ||
ASSERT_EQ(4, filter->NumKeys()); | ||
// 1 is first compacted to L1 and then further compacted into [2, 4, 8], | ||
// so finally the logged level for 1 is L1. | ||
ASSERT_EQ(1, filter->KeyLevel("1")); | ||
// 1 is first compacted from L0 to L1, and then L1 intra level compaction | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New behavior for |
||
// compacts [2, 4, 8] only. | ||
ASSERT_EQ(0, filter->KeyLevel("1")); | ||
ASSERT_EQ(1, filter->KeyLevel("2")); | ||
ASSERT_EQ(1, filter->KeyLevel("4")); | ||
ASSERT_EQ(1, filter->KeyLevel("8")); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
For Leveled Compaction users, `CompactRange()` will now always try to compact to the last non-empty level. (#11468) | ||
For Leveled Compaction users, `CompactRange()` with `bottommost_level_compaction = BottommostLevelCompaction::kIfHaveCompactionFilter` will behave similar to `kForceOptimized` in that it will skip files created during this manual compaction when compacting files in the bottommost level. (#11468) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple trivial moves to compact to the bottommost level.