This is an automated email from the ASF dual-hosted git repository.
gavinchou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new a1e076e8d69 [fix](compaction) Avoid repeatedly compacting large
cumulative rowset (#64954)
a1e076e8d69 is described below
commit a1e076e8d6969feafd8411f7b19e22664f43c543
Author: Jamie <[email protected]>
AuthorDate: Tue Jul 14 19:47:35 2026 +0800
[fix](compaction) Avoid repeatedly compacting large cumulative rowset
(#64954)
## Proposed changes
- Remove the promotion-size early return in size-based cumulative
compaction rowset selection so level-size trimming can exclude an
oversized leading rowset.
- Keep the level-size trimming loop from trimming a single candidate
rowset to an empty input set.
- Apply the same behavior to both cloud and storage cumulative
compaction policies.
- Add regression coverage for the large-head/small-tail case and the
single-rowset guard in both paths.
---
.../cloud/cloud_cumulative_compaction_policy.cpp | 17 +-
.../compaction/cumulative_compaction_policy.cpp | 16 +-
.../cloud_cumulative_compaction_policy_test.cpp | 118 ++++++++++-
.../cumulative_compaction_policy_test.cpp | 230 ++++++++++++++++++++-
4 files changed, 363 insertions(+), 18 deletions(-)
diff --git a/be/src/cloud/cloud_cumulative_compaction_policy.cpp
b/be/src/cloud/cloud_cumulative_compaction_policy.cpp
index 834b9b682ea..ca422be9b24 100644
--- a/be/src/cloud/cloud_cumulative_compaction_policy.cpp
+++ b/be/src/cloud/cloud_cumulative_compaction_policy.cpp
@@ -18,6 +18,7 @@
#include "cloud/cloud_cumulative_compaction_policy.h"
#include <algorithm>
+#include <iterator>
#include <list>
#include <ostream>
#include <string>
@@ -172,10 +173,6 @@ int64_t
CloudSizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
input_rowsets->push_back(rowset);
}
- if (total_size >= promotion_size) {
- return transient_size;
- }
-
// if there is delete version, do compaction directly
if (last_delete_version->first != -1) {
if (input_rowsets->size() == 1) {
@@ -212,6 +209,9 @@ int64_t
CloudSizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
auto rs_begin = input_rowsets->begin();
size_t new_compaction_score = *compaction_score;
+ const bool can_handle_exhausted_input =
+ (config::prioritize_query_perf_in_compaction &&
tablet->keys_type() != DUP_KEYS) ||
+ *compaction_score >= static_cast<size_t>(max_compaction_score);
while (rs_begin != input_rowsets->end()) {
auto& rs_meta = (*rs_begin)->rowset_meta();
int64_t current_level = _level_size(rs_meta->total_disk_size());
@@ -221,9 +221,16 @@ int64_t
CloudSizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
if (current_level <= remain_level) {
break;
}
+
+ auto next = std::next(rs_begin);
+ // Keep the last suffix rowset for the singleton checks unless the
exhausted-input
+ // fallback below can select a useful input.
+ if (next == input_rowsets->end() && !can_handle_exhausted_input) {
+ break;
+ }
total_size -= rs_meta->total_disk_size();
new_compaction_score -= rs_meta->get_compaction_score();
- ++rs_begin;
+ rs_begin = next;
}
if (rs_begin == input_rowsets->end()) { // No suitable level size found in
`input_rowsets`
if (config::prioritize_query_perf_in_compaction && tablet->keys_type()
!= DUP_KEYS) {
diff --git a/be/src/storage/compaction/cumulative_compaction_policy.cpp
b/be/src/storage/compaction/cumulative_compaction_policy.cpp
index 4ab59709590..a120d941e6f 100644
--- a/be/src/storage/compaction/cumulative_compaction_policy.cpp
+++ b/be/src/storage/compaction/cumulative_compaction_policy.cpp
@@ -18,6 +18,7 @@
#include "storage/compaction/cumulative_compaction_policy.h"
#include <algorithm>
+#include <iterator>
#include <list>
#include <ostream>
#include <string>
@@ -318,10 +319,6 @@ int
SizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
DBUG_EXECUTE_IF("SizeBaseCumulativeCompactionPolicy.pick_input_rowsets.return_input_rowsets",
{ return transient_size; })
- if (total_size >= promotion_size) {
- return transient_size;
- }
-
// if there is delete version, do compaction directly
if (last_delete_version->first != -1) {
if (input_rowsets->size() == 1) {
@@ -338,6 +335,8 @@ int SizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
auto rs_begin = input_rowsets->begin();
size_t new_compaction_score = *compaction_score;
+ const bool can_handle_exhausted_input =
+ *compaction_score >= static_cast<size_t>(max_compaction_score);
while (rs_begin != input_rowsets->end()) {
auto& rs_meta = (*rs_begin)->rowset_meta();
int64_t current_level = _level_size(rs_meta->total_disk_size());
@@ -347,9 +346,16 @@ int
SizeBasedCumulativeCompactionPolicy::pick_input_rowsets(
if (current_level <= remain_level) {
break;
}
+
+ auto next = std::next(rs_begin);
+ // Keep the last suffix rowset for the singleton checks unless the
exhausted-input
+ // fallback below can select a useful input.
+ if (next == input_rowsets->end() && !can_handle_exhausted_input) {
+ break;
+ }
total_size -= rs_meta->total_disk_size();
new_compaction_score -= rs_meta->get_compaction_score();
- ++rs_begin;
+ rs_begin = next;
}
if (rs_begin == input_rowsets->end() && *compaction_score >=
max_compaction_score) {
// No suitable level size found in `input_rowsets` but score of
`input_rowsets` exceed max compaction score,
diff --git a/be/test/cloud/cloud_cumulative_compaction_policy_test.cpp
b/be/test/cloud/cloud_cumulative_compaction_policy_test.cpp
index 29358eaaee0..08799c900d2 100644
--- a/be/test/cloud/cloud_cumulative_compaction_policy_test.cpp
+++ b/be/test/cloud/cloud_cumulative_compaction_policy_test.cpp
@@ -36,6 +36,9 @@
namespace doris {
+static constexpr int64_t kMiB = 1024L * 1024;
+static constexpr int64_t kGiB = 1024L * kMiB;
+
class TestCloudSizeBasedCumulativeCompactionPolicy : public testing::Test {
public:
TestCloudSizeBasedCumulativeCompactionPolicy()
@@ -118,7 +121,7 @@ private:
};
static RowsetSharedPtr create_rowset(Version version, int num_segments, bool
overlapping,
- int data_size) {
+ int64_t data_size) {
auto rs_meta = std::make_shared<RowsetMeta>();
rs_meta->set_rowset_type(BETA_ROWSET); // important
rs_meta->_rowset_meta_pb.set_start_version(version.first);
@@ -134,6 +137,14 @@ static RowsetSharedPtr create_rowset(Version version, int
num_segments, bool ove
return rowset;
}
+static int64_t total_disk_size(const std::vector<RowsetSharedPtr>& rowsets) {
+ int64_t total_size = 0;
+ for (const auto& rowset : rowsets) {
+ total_size += rowset->total_disk_size();
+ }
+ return total_size;
+}
+
TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy, new_cumulative_point) {
std::vector<RowsetMetaSharedPtr> rs_metas;
init_rs_meta_small_base(&rs_metas);
@@ -151,6 +162,111 @@ TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
new_cumulative_point) {
EXPECT_EQ(policy.new_cumulative_point(&_tablet, output_rowset, version,
2), 6);
}
+TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_large_head_not_repeated_when_output_below_promotion)
{
+ CloudTablet _tablet(_engine, _tablet_meta);
+ _tablet._base_size = 20L * kGiB;
+
+ std::vector<RowsetSharedPtr> candidate_rowsets;
+ auto large_head = create_rowset(Version(2, 2), 1, false, 1023L * kMiB);
+ candidate_rowsets.push_back(large_head);
+ for (int i = 0; i < 20; i++) {
+ candidate_rowsets.push_back(create_rowset(Version(i + 3, i + 3), 1,
true, kMiB));
+ }
+ ASSERT_GT(total_disk_size(candidate_rowsets), kGiB);
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ CloudSizeBasedCumulativeCompactionPolicy policy;
+ policy.pick_input_rowsets(&_tablet, candidate_rowsets, 100, 5,
&input_rowsets,
+ &last_delete_version, &compaction_score, true);
+
+ EXPECT_EQ(20, input_rowsets.size());
+ EXPECT_EQ(20, compaction_score);
+ EXPECT_EQ(3, input_rowsets.front()->start_version());
+ EXPECT_EQ(22, input_rowsets.back()->end_version());
+ EXPECT_LT(total_disk_size(input_rowsets), kGiB);
+
+ auto output_rowset = create_rowset(Version(3, 22), 1, false, 20L * kMiB);
+ EXPECT_EQ(2, policy.new_cumulative_point(&_tablet, output_rowset,
last_delete_version, 2));
+
+ std::vector<RowsetSharedPtr> next_candidate_rowsets {large_head,
output_rowset};
+ input_rowsets.clear();
+ compaction_score = 0;
+ policy.pick_input_rowsets(&_tablet, next_candidate_rowsets, 100, 5,
&input_rowsets,
+ &last_delete_version, &compaction_score, true);
+
+ EXPECT_TRUE(input_rowsets.empty());
+ EXPECT_EQ(0, compaction_score);
+}
+
+TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_large_head_single_overlapping_tail_selected) {
+ CloudTablet _tablet(_engine, _tablet_meta);
+ _tablet._base_size = 20L * kGiB;
+
+ std::vector<RowsetSharedPtr> candidate_rowsets {
+ create_rowset(Version(2, 2), 1, false, 900L * kMiB),
+ create_rowset(Version(3, 3), 5, true, 128L * kMiB)};
+ ASSERT_GT(total_disk_size(candidate_rowsets), kGiB);
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ CloudSizeBasedCumulativeCompactionPolicy policy;
+ policy.pick_input_rowsets(&_tablet, candidate_rowsets, 100, 5,
&input_rowsets,
+ &last_delete_version, &compaction_score, true);
+
+ ASSERT_EQ(1, input_rowsets.size());
+ EXPECT_EQ(5, compaction_score);
+ EXPECT_EQ(3, input_rowsets.front()->start_version());
+ EXPECT_EQ(128L * kMiB, input_rowsets.front()->total_disk_size());
+}
+
+TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_single_overlapping_rowset_not_trimmed_empty) {
+ CloudTablet _tablet(_engine, _tablet_meta);
+ _tablet._base_size = 20L * kGiB;
+
+ std::vector<RowsetSharedPtr> candidate_rowsets {
+ create_rowset(Version(2, 2), 3, true, 2L * kGiB)};
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ CloudSizeBasedCumulativeCompactionPolicy policy;
+ policy.pick_input_rowsets(&_tablet, candidate_rowsets, 100, 5,
&input_rowsets,
+ &last_delete_version, &compaction_score, true);
+
+ EXPECT_EQ(1, input_rowsets.size());
+ EXPECT_EQ(3, compaction_score);
+ EXPECT_EQ(2, input_rowsets.front()->start_version());
+}
+
+TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_single_non_overlapping_rowset_still_skipped) {
+ CloudTablet _tablet(_engine, _tablet_meta);
+ _tablet._base_size = 20L * kGiB;
+
+ std::vector<RowsetSharedPtr> candidate_rowsets {
+ create_rowset(Version(2, 2), 1, false, 2L * kGiB)};
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ CloudSizeBasedCumulativeCompactionPolicy policy;
+ policy.pick_input_rowsets(&_tablet, candidate_rowsets, 100, 5,
&input_rowsets,
+ &last_delete_version, &compaction_score, true);
+
+ EXPECT_TRUE(input_rowsets.empty());
+ EXPECT_EQ(0, compaction_score);
+}
+
// Test case: Empty rowset compaction with skip_trim
TEST_F(TestCloudSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_empty_rowset_compaction) {
// Save original config values
diff --git a/be/test/storage/compaction/cumulative_compaction_policy_test.cpp
b/be/test/storage/compaction/cumulative_compaction_policy_test.cpp
index b0573ead66b..58b18128b86 100644
--- a/be/test/storage/compaction/cumulative_compaction_policy_test.cpp
+++ b/be/test/storage/compaction/cumulative_compaction_policy_test.cpp
@@ -26,6 +26,7 @@
#include "json2pb/json_to_pb.h"
#include "storage/compaction/cumulative_compaction.h"
#include "storage/olap_common.h"
+#include "storage/rowset/rowset_factory.h"
#include "storage/rowset/rowset_meta.h"
#include "storage/storage_engine.h"
#include "storage/tablet/tablet.h"
@@ -34,6 +35,9 @@
namespace doris {
+static constexpr int64_t kMiB = 1024L * 1024;
+static constexpr int64_t kGiB = 1024L * kMiB;
+
class TestSizeBasedCumulativeCompactionPolicy : public testing::Test {
public:
TestSizeBasedCumulativeCompactionPolicy() : _engine(StorageEngine({})) {}
@@ -1085,6 +1089,218 @@ TEST_F(TestSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_trim_after_pr
EXPECT_EQ(100, input_rowsets.size());
}
+TEST_F(TestSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_large_head_not_repeated_when_output_below_promotion)
{
+ std::vector<RowsetMetaSharedPtr> rs_metas;
+
+ RowsetMetaSharedPtr base_rs(new RowsetMeta());
+ init_rs_meta(base_rs, 0, 1);
+ base_rs->set_total_disk_size(20L * kGiB);
+ base_rs->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(base_rs);
+
+ RowsetMetaSharedPtr large_head(new RowsetMeta());
+ init_rs_meta(large_head, 2, 2);
+ large_head->set_total_disk_size(1023L * kMiB);
+ large_head->set_num_segments(1);
+ large_head->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(large_head);
+
+ for (int i = 0; i < 20; i++) {
+ RowsetMetaSharedPtr ptr(new RowsetMeta());
+ init_rs_meta(ptr, i + 3, i + 3);
+ ptr->set_total_disk_size(kMiB);
+ ptr->set_num_segments(1);
+ ptr->set_segments_overlap(OVERLAPPING);
+ rs_metas.push_back(ptr);
+ }
+
+ for (auto& rowset : rs_metas) {
+ static_cast<void>(_tablet_meta->add_rs_meta(rowset));
+ }
+
+ TabletSharedPtr _tablet(
+ new Tablet(_engine, _tablet_meta, nullptr,
CUMULATIVE_SIZE_BASED_POLICY));
+ static_cast<void>(_tablet->init());
+ _tablet->calculate_cumulative_point();
+ ASSERT_EQ(2, _tablet->cumulative_layer_point());
+ ASSERT_EQ(kGiB, _tablet->cumulative_promotion_size());
+
+ auto candidate_rowsets =
_tablet->pick_candidate_rowsets_to_cumulative_compaction();
+ ASSERT_EQ(21, candidate_rowsets.size());
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ _tablet->_cumulative_compaction_policy->pick_input_rowsets(
+ _tablet.get(), candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
+ &compaction_score, config::enable_delete_when_cumu_compaction);
+
+ EXPECT_EQ(20, input_rowsets.size());
+ EXPECT_EQ(20, compaction_score);
+ EXPECT_EQ(3, input_rowsets.front()->start_version());
+ EXPECT_EQ(22, input_rowsets.back()->end_version());
+
+ RowsetMetaSharedPtr output_meta(new RowsetMeta());
+ init_rs_meta(output_meta, 3, 22);
+ output_meta->set_total_disk_size(20L * kMiB);
+ output_meta->set_num_segments(1);
+ output_meta->set_segments_overlap(NONOVERLAPPING);
+ RowsetSharedPtr output_rowset;
+ ASSERT_TRUE(RowsetFactory::create_rowset(nullptr, "", output_meta,
&output_rowset).ok());
+
+ _tablet->_cumulative_compaction_policy->update_cumulative_point(
+ _tablet.get(), input_rowsets, output_rowset, last_delete_version);
+ EXPECT_EQ(2, _tablet->cumulative_layer_point());
+
+ std::vector<RowsetSharedPtr> next_candidate_rowsets
{candidate_rowsets.front(), output_rowset};
+ input_rowsets.clear();
+ compaction_score = 0;
+ _tablet->_cumulative_compaction_policy->pick_input_rowsets(
+ _tablet.get(), next_candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
+ &compaction_score, config::enable_delete_when_cumu_compaction);
+
+ EXPECT_TRUE(input_rowsets.empty());
+ EXPECT_EQ(0, compaction_score);
+}
+
+TEST_F(TestSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_large_head_single_overlapping_tail_selected) {
+ std::vector<RowsetMetaSharedPtr> rs_metas;
+
+ RowsetMetaSharedPtr base_rs(new RowsetMeta());
+ init_rs_meta(base_rs, 0, 1);
+ base_rs->set_total_disk_size(20L * kGiB);
+ base_rs->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(base_rs);
+
+ RowsetMetaSharedPtr large_head(new RowsetMeta());
+ init_rs_meta(large_head, 2, 2);
+ large_head->set_total_disk_size(900L * kMiB);
+ large_head->set_num_segments(1);
+ large_head->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(large_head);
+
+ RowsetMetaSharedPtr tail(new RowsetMeta());
+ init_rs_meta(tail, 3, 3);
+ tail->set_total_disk_size(128L * kMiB);
+ tail->set_num_segments(5);
+ tail->set_segments_overlap(OVERLAPPING);
+ rs_metas.push_back(tail);
+
+ for (auto& rowset : rs_metas) {
+ static_cast<void>(_tablet_meta->add_rs_meta(rowset));
+ }
+
+ TabletSharedPtr _tablet(
+ new Tablet(_engine, _tablet_meta, nullptr,
CUMULATIVE_SIZE_BASED_POLICY));
+ static_cast<void>(_tablet->init());
+ _tablet->calculate_cumulative_point();
+ ASSERT_EQ(2, _tablet->cumulative_layer_point());
+ ASSERT_EQ(kGiB, _tablet->cumulative_promotion_size());
+
+ auto candidate_rowsets =
_tablet->pick_candidate_rowsets_to_cumulative_compaction();
+ ASSERT_EQ(2, candidate_rowsets.size());
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ _tablet->_cumulative_compaction_policy->pick_input_rowsets(
+ _tablet.get(), candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
+ &compaction_score, config::enable_delete_when_cumu_compaction);
+
+ ASSERT_EQ(1, input_rowsets.size());
+ EXPECT_EQ(5, compaction_score);
+ EXPECT_EQ(3, input_rowsets.front()->start_version());
+ EXPECT_EQ(128L * kMiB, input_rowsets.front()->total_disk_size());
+}
+
+TEST_F(TestSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_single_overlapping_rowset_not_trimmed_empty) {
+ std::vector<RowsetMetaSharedPtr> rs_metas;
+
+ RowsetMetaSharedPtr base_rs(new RowsetMeta());
+ init_rs_meta(base_rs, 0, 1);
+ base_rs->set_total_disk_size(20L * kGiB);
+ base_rs->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(base_rs);
+
+ RowsetMetaSharedPtr ptr(new RowsetMeta());
+ init_rs_meta(ptr, 2, 2);
+ ptr->set_total_disk_size(2L * kGiB);
+ ptr->set_num_segments(3);
+ ptr->set_segments_overlap(OVERLAPPING);
+ rs_metas.push_back(ptr);
+
+ for (auto& rowset : rs_metas) {
+ static_cast<void>(_tablet_meta->add_rs_meta(rowset));
+ }
+
+ TabletSharedPtr _tablet(
+ new Tablet(_engine, _tablet_meta, nullptr,
CUMULATIVE_SIZE_BASED_POLICY));
+ static_cast<void>(_tablet->init());
+ _tablet->calculate_cumulative_point();
+
+ auto candidate_rowsets =
_tablet->pick_candidate_rowsets_to_cumulative_compaction();
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ _tablet->_cumulative_compaction_policy->pick_input_rowsets(
+ _tablet.get(), candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
+ &compaction_score, config::enable_delete_when_cumu_compaction);
+
+ EXPECT_EQ(1, input_rowsets.size());
+ EXPECT_EQ(3, compaction_score);
+ EXPECT_EQ(2, input_rowsets.front()->start_version());
+}
+
+TEST_F(TestSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_single_non_overlapping_rowset_still_skipped) {
+ std::vector<RowsetMetaSharedPtr> rs_metas;
+
+ RowsetMetaSharedPtr base_rs(new RowsetMeta());
+ init_rs_meta(base_rs, 0, 1);
+ base_rs->set_total_disk_size(20L * kGiB);
+ base_rs->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(base_rs);
+
+ RowsetMetaSharedPtr ptr(new RowsetMeta());
+ init_rs_meta(ptr, 2, 2);
+ ptr->set_total_disk_size(2L * kGiB);
+ ptr->set_num_segments(1);
+ ptr->set_segments_overlap(NONOVERLAPPING);
+ rs_metas.push_back(ptr);
+
+ for (auto& rowset : rs_metas) {
+ static_cast<void>(_tablet_meta->add_rs_meta(rowset));
+ }
+
+ TabletSharedPtr _tablet(
+ new Tablet(_engine, _tablet_meta, nullptr,
CUMULATIVE_SIZE_BASED_POLICY));
+ static_cast<void>(_tablet->init());
+ _tablet->calculate_cumulative_point();
+
+ std::vector<RowsetSharedPtr> candidate_rowsets;
+ RowsetSharedPtr rowset;
+ ASSERT_TRUE(RowsetFactory::create_rowset(nullptr, "", ptr, &rowset).ok());
+ candidate_rowsets.push_back(rowset);
+
+ std::vector<RowsetSharedPtr> input_rowsets;
+ Version last_delete_version {-1, -1};
+ size_t compaction_score = 0;
+
+ _tablet->_cumulative_compaction_policy->pick_input_rowsets(
+ _tablet.get(), candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
+ &compaction_score, config::enable_delete_when_cumu_compaction);
+
+ EXPECT_TRUE(input_rowsets.empty());
+ EXPECT_EQ(0, compaction_score);
+}
+
// Test case: Trim with varying scores (high score rowsets at tail)
TEST_F(TestSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_trim_high_score_tail) {
std::vector<RowsetMetaSharedPtr> rs_metas;
@@ -1765,8 +1981,9 @@ TEST_F(TestSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_single_non_ov
EXPECT_EQ(0, compaction_score);
}
-// Test case: Fallback when all removed by level_size but score < max
-TEST_F(TestSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_fallback_score_below_max) {
+// Test case: Keep the final overlapping suffix when exhausted-input fallback
is unavailable
+TEST_F(TestSizeBasedCumulativeCompactionPolicy,
+ pick_input_rowsets_keep_final_overlapping_below_max) {
std::vector<RowsetMetaSharedPtr> rs_metas;
// Base rowset: 20GB
@@ -1807,15 +2024,14 @@ TEST_F(TestSizeBasedCumulativeCompactionPolicy,
pick_input_rowsets_fallback_scor
Version last_delete_version {-1, -1};
size_t compaction_score = 0;
- // All rowsets removed by level_size, score=50 < max=100
- // Does not trigger fallback, goes to normal flow with empty result
+ // The original score is below max, so the loop must stop before removing
the final rowset.
_tablet->_cumulative_compaction_policy->pick_input_rowsets(
_tablet.get(), candidate_rowsets, 100, 5, &input_rowsets,
&last_delete_version,
&compaction_score, config::enable_delete_when_cumu_compaction);
- // After level_size removes all, result is empty (no fallback since score
< max)
- EXPECT_EQ(0, input_rowsets.size());
- EXPECT_EQ(0, compaction_score);
+ ASSERT_EQ(1, input_rowsets.size());
+ EXPECT_EQ(20, compaction_score);
+ EXPECT_EQ(3, input_rowsets.front()->start_version());
}
// Test case: level_size removes large head, then trim after
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]