This is an automated email from the ASF dual-hosted git repository.
Yukang-Lian 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 ee0aa56f7e1 [improvement](compaction) split time series compaction
score metric (#63900)
ee0aa56f7e1 is described below
commit ee0aa56f7e1561c92a8532e60a7fde374dd224ec
Author: Jamie <[email protected]>
AuthorDate: Tue Aug 11 15:51:38 2026 +0800
[improvement](compaction) split time series compaction score metric (#63900)
### What problem does this PR solve?
Before this change, BE exposes only the aggregate cumulative compaction
score:
```bash
curl -s http://<be_host>:<webserver_port>/metrics \
| grep 'doris_be_tablet_cumulative_max_compaction_score'
```
The aggregate value cannot show which cumulative compaction policy
contributes the maximum score.
After this change, observe the aggregate and per-policy scores with:
```bash
curl -s http://<be_host>:<webserver_port>/metrics \
| grep -E
'doris_be_tablet_(cumulative|size_based|time_series)_max_compaction_score'
```
| Metric | Meaning |
| --- | --- |
| `doris_be_tablet_cumulative_max_compaction_score` | Maximum score
across all cumulative compaction policies; semantics unchanged |
| `doris_be_tablet_size_based_max_compaction_score` | Maximum score from
the size-based policy |
| `doris_be_tablet_time_series_max_compaction_score` | Maximum score
from the time-series policy |
New behavior:
- Local and Cloud BEs publish the two per-policy metrics.
- The existing aggregate metric and BE report value `max(base,
cumulative)` remain unchanged.
- Compaction score calculation, tablet ranking, and tablet selection are
unchanged.
- A complete score check can reset a missing policy score to zero; an
incomplete local scan caused by capacity-limited disks does not lower
the cumulative score metrics.
### Release note
Add separate size-based and time-series cumulative compaction score
metrics while preserving the existing aggregate metric.
---
be/src/cloud/cloud_storage_engine.cpp | 36 +++-
be/src/cloud/cloud_storage_engine.h | 5 +
be/src/cloud/cloud_tablet_mgr.cpp | 21 +-
be/src/cloud/cloud_tablet_mgr.h | 4 +-
be/src/common/metrics/doris_metrics.cpp | 4 +
be/src/common/metrics/doris_metrics.h | 6 +-
be/src/storage/data_dir.h | 7 +
be/src/storage/olap_common.h | 7 +
be/src/storage/olap_server.cpp | 84 +++++---
be/src/storage/storage_engine.h | 20 +-
be/src/storage/tablet/tablet_manager.cpp | 41 +++-
be/src/storage/tablet/tablet_manager.h | 3 +-
be/test/cloud/cloud_compaction_test.cpp | 172 +++++++++++++++-
be/test/storage/tablet/tablet_mgr_test.cpp | 316 ++++++++++++++++++++++++++++-
be/test/util/doris_metrics_test.cpp | 12 ++
15 files changed, 663 insertions(+), 75 deletions(-)
diff --git a/be/src/cloud/cloud_storage_engine.cpp
b/be/src/cloud/cloud_storage_engine.cpp
index 19514d647d3..a8cebc7449d 100644
--- a/be/src/cloud/cloud_storage_engine.cpp
+++ b/be/src/cloud/cloud_storage_engine.cpp
@@ -761,9 +761,13 @@ bool CloudStorageEngine::register_index_change_compaction(
std::vector<CloudTabletSPtr>
CloudStorageEngine::_generate_cloud_compaction_tasks(
CompactionType compaction_type, bool check_score) {
+ DCHECK(compaction_type == CompactionType::BASE_COMPACTION ||
+ compaction_type == CompactionType::CUMULATIVE_COMPACTION ||
+ compaction_type == CompactionType::CUMU_BINLOG_COMPACTION);
std::vector<std::shared_ptr<CloudTablet>> tablets_compaction;
- int64_t max_compaction_score = 0;
+ CompactionScoreStats score_stats;
+ bool got_score_stats = false;
std::unordered_set<int64_t> tablet_preparing_cumu_compaction;
std::unordered_map<int64_t,
std::vector<std::shared_ptr<CloudCumulativeCompaction>>>
submitted_cumu_compactions;
@@ -860,25 +864,37 @@ std::vector<CloudTabletSPtr>
CloudStorageEngine::_generate_cloud_compaction_task
do {
std::vector<CloudTabletSPtr> tablets;
auto st = tablet_mgr().get_topn_tablets_to_compact(n, compaction_type,
filter_out, &tablets,
-
&max_compaction_score);
+ &score_stats);
if (!st.ok()) {
LOG(WARNING) << "failed to get tablets to compact, err=" << st;
break;
}
+ got_score_stats = true;
if (!need_pick_tablet) break;
tablets_compaction = std::move(tablets);
} while (false);
- if (max_compaction_score > 0) {
- if (compaction_type == CompactionType::BASE_COMPACTION) {
+ if (got_score_stats && score_stats.scanned) {
+ if (compaction_type == CompactionType::BASE_COMPACTION &&
score_stats.max_score > 0) {
DorisMetrics::instance()->tablet_base_max_compaction_score->set_value(
- max_compaction_score);
- } else if (compaction_type == CompactionType::CUMU_BINLOG_COMPACTION) {
+ score_stats.max_score);
+ } else if (compaction_type == CompactionType::CUMULATIVE_COMPACTION) {
+ if (check_score || score_stats.max_score > 0) {
+
DorisMetrics::instance()->tablet_cumulative_max_compaction_score->set_value(
+ score_stats.max_score);
+ }
+ if (check_score || score_stats.size_based_max_score > 0) {
+
DorisMetrics::instance()->tablet_size_based_max_compaction_score->set_value(
+ score_stats.size_based_max_score);
+ }
+ if (check_score || score_stats.time_series_max_score > 0) {
+
DorisMetrics::instance()->tablet_time_series_max_compaction_score->set_value(
+ score_stats.time_series_max_score);
+ }
+ } else if (compaction_type == CompactionType::CUMU_BINLOG_COMPACTION &&
+ score_stats.max_score > 0) {
DorisMetrics::instance()->tablet_binlog_max_compaction_score->set_value(
- max_compaction_score);
- } else {
-
DorisMetrics::instance()->tablet_cumulative_max_compaction_score->set_value(
- max_compaction_score);
+ score_stats.max_score);
}
}
diff --git a/be/src/cloud/cloud_storage_engine.h
b/be/src/cloud/cloud_storage_engine.h
index b3f4de73137..330850b5ed8 100644
--- a/be/src/cloud/cloud_storage_engine.h
+++ b/be/src/cloud/cloud_storage_engine.h
@@ -199,6 +199,11 @@ public:
void set_cloud_warm_up_manager(std::unique_ptr<CloudWarmUpManager>
manager);
void init_calc_delete_bitmap_executor_for_UT();
+
+ std::vector<CloudTabletSPtr> generate_cloud_compaction_tasks_for_test(
+ CompactionType compaction_type, bool check_score) {
+ return _generate_cloud_compaction_tasks(compaction_type, check_score);
+ }
#endif
private:
diff --git a/be/src/cloud/cloud_tablet_mgr.cpp
b/be/src/cloud/cloud_tablet_mgr.cpp
index b46ebdc0429..3affe632996 100644
--- a/be/src/cloud/cloud_tablet_mgr.cpp
+++ b/be/src/cloud/cloud_tablet_mgr.cpp
@@ -29,6 +29,7 @@
#include "common/status.h"
#include "cpp/sync_point.h"
#include "runtime/memory/cache_policy.h"
+#include "storage/compaction/cumulative_compaction_time_series_policy.h"
#include "util/debug_points.h"
#include "util/lru_cache.h"
#include "util/stack_util.h"
@@ -432,11 +433,12 @@ void CloudTabletMgr::sync_tablets(const CountDownLatch&
stop_latch) {
Status CloudTabletMgr::get_topn_tablets_to_compact(
int n, CompactionType compaction_type, const
std::function<bool(CloudTablet*)>& filter_out,
- std::vector<std::shared_ptr<CloudTablet>>* tablets, int64_t*
max_score) {
+ std::vector<std::shared_ptr<CloudTablet>>* tablets,
CompactionScoreStats* score_stats) {
DCHECK(compaction_type == CompactionType::BASE_COMPACTION ||
compaction_type == CompactionType::CUMULATIVE_COMPACTION ||
compaction_type == CompactionType::CUMU_BINLOG_COMPACTION);
- *max_score = 0;
+ *score_stats = {};
+ score_stats->scanned = true;
int64_t max_score_tablet_id = 0;
// clang-format off
auto score = [compaction_type](CloudTablet* t) {
@@ -503,9 +505,18 @@ Status CloudTabletMgr::get_topn_tablets_to_compact(
int64_t s = score(t.get());
if (s <= 0) { continue; }
- if (s > *max_score) {
+ if (s > score_stats->max_score) {
max_score_tablet_id = t->tablet_id();
- *max_score = s;
+ score_stats->max_score = s;
+ }
+ if (compaction_type == CompactionType::CUMULATIVE_COMPACTION) {
+ int64_t* policy_max_score =
+ t->tablet_meta()->compaction_policy() ==
CUMULATIVE_TIME_SERIES_POLICY
+ ? &score_stats->time_series_max_score
+ : &score_stats->size_based_max_score;
+ if (s > *policy_max_score) {
+ *policy_max_score = s;
+ }
}
if (filter_out(t.get())) { ++num_filtered; continue; }
@@ -520,7 +531,7 @@ Status CloudTabletMgr::get_topn_tablets_to_compact(
LOG_EVERY_N(INFO, 1000) << "get_topn_compaction_score, n=" << n << "
type=" << compaction_type
<< " num_tablets=" << weak_tablets.size() << " num_skipped=" <<
num_skipped
<< " num_disabled=" << num_disabled << " num_filtered=" <<
num_filtered
- << " max_score=" << *max_score << " max_score_tablet=" <<
max_score_tablet_id
+ << " max_score=" << score_stats->max_score << "
max_score_tablet=" << max_score_tablet_id
<< " tablets=[" << [&buf] { std::stringstream ss; for (auto& i
: buf) ss << i.first->tablet_id() << ":" << i.second << ","; return ss.str();
}() << "]"
;
// clang-format on
diff --git a/be/src/cloud/cloud_tablet_mgr.h b/be/src/cloud/cloud_tablet_mgr.h
index 9894d97552b..c44f4f36f8c 100644
--- a/be/src/cloud/cloud_tablet_mgr.h
+++ b/be/src/cloud/cloud_tablet_mgr.h
@@ -79,13 +79,13 @@ public:
* @param filter_out a filter takes a tablet and return bool to check
* whether skipping the tablet, true for skip
* @param tablets output param
- * @param max_score output param, max score of existed tablets
+ * @param score_stats output param, max scores of existed tablets
* @return status of this call
*/
Status get_topn_tablets_to_compact(int n, CompactionType compaction_type,
const
std::function<bool(CloudTablet*)>& filter_out,
std::vector<std::shared_ptr<CloudTablet>>* tablets,
- int64_t* max_score);
+ CompactionScoreStats* score_stats);
/**
* Gets tablets info and total tablet num that are reported
diff --git a/be/src/common/metrics/doris_metrics.cpp
b/be/src/common/metrics/doris_metrics.cpp
index 36bebcddbb3..3799a95da05 100644
--- a/be/src/common/metrics/doris_metrics.cpp
+++ b/be/src/common/metrics/doris_metrics.cpp
@@ -195,6 +195,8 @@
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(process_fd_num_limit_soft, MetricUnit::NOUNIT
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(process_fd_num_limit_hard,
MetricUnit::NOUNIT);
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(tablet_cumulative_max_compaction_score,
MetricUnit::NOUNIT);
+DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(tablet_size_based_max_compaction_score,
MetricUnit::NOUNIT);
+DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(tablet_time_series_max_compaction_score,
MetricUnit::NOUNIT);
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(tablet_base_max_compaction_score,
MetricUnit::NOUNIT);
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(tablet_binlog_max_compaction_score,
MetricUnit::NOUNIT);
@@ -392,6 +394,8 @@ DorisMetrics::DorisMetrics() :
_metric_registry(_s_registry_name) {
INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
process_fd_num_limit_hard);
INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
tablet_cumulative_max_compaction_score);
+ INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
tablet_size_based_max_compaction_score);
+ INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
tablet_time_series_max_compaction_score);
INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
tablet_base_max_compaction_score);
INT_GAUGE_METRIC_REGISTER(_server_metric_entity,
tablet_binlog_max_compaction_score);
diff --git a/be/src/common/metrics/doris_metrics.h
b/be/src/common/metrics/doris_metrics.h
index aadda83fa86..2973435305a 100644
--- a/be/src/common/metrics/doris_metrics.h
+++ b/be/src/common/metrics/doris_metrics.h
@@ -165,9 +165,11 @@ public:
IntGauge* process_fd_num_limit_hard = nullptr;
// the max compaction score of all tablets.
- // Record base and cumulative scores separately, because
- // we need to get the larger of the two.
+ // Keep the cumulative score as the aggregate for compatibility, and record
+ // size-based and time-series cumulative scores separately.
IntGauge* tablet_cumulative_max_compaction_score = nullptr;
+ IntGauge* tablet_size_based_max_compaction_score = nullptr;
+ IntGauge* tablet_time_series_max_compaction_score = nullptr;
IntGauge* tablet_base_max_compaction_score = nullptr;
IntGauge* tablet_binlog_max_compaction_score = nullptr;
diff --git a/be/src/storage/data_dir.h b/be/src/storage/data_dir.h
index 4598f3d8771..f5a2c57f33f 100644
--- a/be/src/storage/data_dir.h
+++ b/be/src/storage/data_dir.h
@@ -141,6 +141,13 @@ public:
(double)_disk_capacity_bytes;
}
+#ifdef BE_TEST
+ void set_capacity_for_test(size_t disk_capacity_bytes, size_t
available_bytes) {
+ _disk_capacity_bytes = disk_capacity_bytes;
+ _available_bytes = available_bytes;
+ }
+#endif
+
// Move tablet to trash.
Status move_to_trash(const std::string& tablet_path);
diff --git a/be/src/storage/olap_common.h b/be/src/storage/olap_common.h
index 12ca1d2e6a4..51f23f93cd1 100644
--- a/be/src/storage/olap_common.h
+++ b/be/src/storage/olap_common.h
@@ -64,6 +64,13 @@ enum CompactionType {
CUMU_BINLOG_COMPACTION = 4
};
+struct CompactionScoreStats {
+ int64_t max_score = 0;
+ int64_t size_based_max_score = 0;
+ int64_t time_series_max_score = 0;
+ bool scanned = false;
+};
+
enum DataDirType {
SPILL_DISK_DIR,
OLAP_DATA_DIR,
diff --git a/be/src/storage/olap_server.cpp b/be/src/storage/olap_server.cpp
index 07143c265ff..07f179f6348 100644
--- a/be/src/storage/olap_server.cpp
+++ b/be/src/storage/olap_server.cpp
@@ -150,11 +150,12 @@ bool
CompactionSubmitRegistry::has_compaction_task(DataDir* dir, CompactionType
std::vector<TabletCompactionContext>
CompactionSubmitRegistry::pick_topn_tablets_for_compaction(
TabletManager* tablet_mgr, DataDir* data_dir, CompactionType
compaction_type,
- const CumuCompactionPolicyTable& cumu_compaction_policies, uint32_t*
disk_max_score) {
+ const CumuCompactionPolicyTable& cumu_compaction_policies,
+ CompactionScoreStats* disk_score_stats) {
// non-lock, used in snapshot
return tablet_mgr->find_best_tablets_to_compaction(compaction_type,
data_dir,
_get_tablet_set(data_dir, compaction_type),
- disk_max_score,
cumu_compaction_policies);
+ disk_score_stats,
cumu_compaction_policies);
}
bool CompactionSubmitRegistry::insert(TabletSharedPtr tablet, CompactionType
compaction_type) {
@@ -845,7 +846,7 @@ bool need_generate_compaction_tasks(int task_cnt_per_disk,
int thread_per_disk,
return true;
}
-int get_concurrent_per_disk(int max_score, int thread_per_disk) {
+int get_concurrent_per_disk(int64_t max_score, int thread_per_disk) {
if (!config::enable_compaction_priority_scheduling) {
return thread_per_disk;
}
@@ -887,12 +888,16 @@ bool has_free_compaction_slot(CompactionSubmitRegistry*
registry, DataDir* dir,
std::vector<TabletCompactionContext> StorageEngine::_generate_compaction_tasks(
CompactionType compaction_type, std::vector<DataDir*>& data_dirs, bool
check_score) {
+ DCHECK(compaction_type == CompactionType::BASE_COMPACTION ||
+ compaction_type == CompactionType::CUMULATIVE_COMPACTION ||
+ compaction_type == CompactionType::CUMU_BINLOG_COMPACTION);
TEST_SYNC_POINT_RETURN_WITH_VALUE("olap_server::_generate_compaction_tasks.return_empty",
std::vector<TabletCompactionContext> {});
_update_cumulative_compaction_policy();
auto cumulative_compaction_policies =
_snapshot_cumulative_compaction_policy();
std::vector<TabletCompactionContext> tablet_compaction_contexts;
- uint32_t max_compaction_score = 0;
+ CompactionScoreStats max_score_stats;
+ bool skipped_capacity_limited_dir = false;
std::random_device rd;
std::mt19937 g(rd());
@@ -916,38 +921,61 @@ std::vector<TabletCompactionContext>
StorageEngine::_generate_compaction_tasks(
// Even if need_pick_tablet is false, we still need to call
find_best_tablet_to_compaction(),
// So that we can update the max_compaction_score metric.
- if (!data_dir->reach_capacity_limit(0)) {
- uint32_t disk_max_score = 0;
- auto tablet_contexts =
compaction_registry_snapshot.pick_topn_tablets_for_compaction(
- _tablet_manager.get(), data_dir, compaction_type,
- cumulative_compaction_policies, &disk_max_score);
- int concurrent_num = get_concurrent_per_disk(
- disk_max_score, disk_compaction_slot_num(*data_dir,
compaction_type));
- need_pick_tablet = need_generate_compaction_tasks(
- executing_task_num, concurrent_num, compaction_type,
- !compaction_registry_snapshot.has_compaction_task(
- data_dir, CompactionType::CUMULATIVE_COMPACTION));
- for (const auto& context : tablet_contexts) {
- if (context.tablet != nullptr) {
- if (need_pick_tablet) {
- tablet_compaction_contexts.emplace_back(context);
- }
- max_compaction_score = std::max(max_compaction_score,
disk_max_score);
+ if (data_dir->reach_capacity_limit(0)) {
+ skipped_capacity_limited_dir = true;
+ continue;
+ }
+
+ CompactionScoreStats disk_score_stats;
+ auto tablet_contexts =
compaction_registry_snapshot.pick_topn_tablets_for_compaction(
+ _tablet_manager.get(), data_dir, compaction_type,
cumulative_compaction_policies,
+ &disk_score_stats);
+ max_score_stats.scanned = max_score_stats.scanned ||
disk_score_stats.scanned;
+ max_score_stats.max_score = std::max(max_score_stats.max_score,
disk_score_stats.max_score);
+ max_score_stats.size_based_max_score =
std::max(max_score_stats.size_based_max_score,
+
disk_score_stats.size_based_max_score);
+ max_score_stats.time_series_max_score =
std::max(max_score_stats.time_series_max_score,
+
disk_score_stats.time_series_max_score);
+ int concurrent_num = get_concurrent_per_disk(
+ disk_score_stats.max_score,
disk_compaction_slot_num(*data_dir, compaction_type));
+ need_pick_tablet = need_generate_compaction_tasks(
+ executing_task_num, concurrent_num, compaction_type,
+ !compaction_registry_snapshot.has_compaction_task(
+ data_dir, CompactionType::CUMULATIVE_COMPACTION));
+ for (const auto& context : tablet_contexts) {
+ if (context.tablet != nullptr) {
+ if (need_pick_tablet) {
+ tablet_compaction_contexts.emplace_back(context);
}
}
}
}
- if (max_compaction_score > 0) {
- if (compaction_type == CompactionType::BASE_COMPACTION) {
+ if (max_score_stats.scanned) {
+ if (compaction_type == CompactionType::BASE_COMPACTION &&
max_score_stats.max_score > 0) {
DorisMetrics::instance()->tablet_base_max_compaction_score->set_value(
- max_compaction_score);
+ max_score_stats.max_score);
} else if (compaction_type == CompactionType::CUMULATIVE_COMPACTION) {
-
DorisMetrics::instance()->tablet_cumulative_max_compaction_score->set_value(
- max_compaction_score);
- } else if (compaction_type == CompactionType::CUMU_BINLOG_COMPACTION) {
+ auto update_policy_score = [skipped_capacity_limited_dir,
check_score](IntGauge* metric,
+
int64_t score) {
+ if (skipped_capacity_limited_dir) {
+ if (score > metric->value()) {
+ metric->set_value(score);
+ }
+ } else if (check_score || score > 0) {
+ metric->set_value(score);
+ }
+ };
+
update_policy_score(DorisMetrics::instance()->tablet_cumulative_max_compaction_score,
+ max_score_stats.max_score);
+
update_policy_score(DorisMetrics::instance()->tablet_size_based_max_compaction_score,
+ max_score_stats.size_based_max_score);
+
update_policy_score(DorisMetrics::instance()->tablet_time_series_max_compaction_score,
+ max_score_stats.time_series_max_score);
+ } else if (compaction_type == CompactionType::CUMU_BINLOG_COMPACTION &&
+ max_score_stats.max_score > 0) {
DorisMetrics::instance()->tablet_binlog_max_compaction_score->set_value(
- max_compaction_score);
+ max_score_stats.max_score);
}
}
return tablet_compaction_contexts;
diff --git a/be/src/storage/storage_engine.h b/be/src/storage/storage_engine.h
index 5530b09dae2..c503fc6cb31 100644
--- a/be/src/storage/storage_engine.h
+++ b/be/src/storage/storage_engine.h
@@ -233,7 +233,8 @@ public:
std::vector<TabletCompactionContext> pick_topn_tablets_for_compaction(
TabletManager* tablet_mgr, DataDir* data_dir, CompactionType
compaction_type,
- const CumuCompactionPolicyTable& cumu_compaction_policies,
uint32_t* disk_max_score);
+ const CumuCompactionPolicyTable& cumu_compaction_policies,
+ CompactionScoreStats* disk_score_stats);
private:
TabletSet& _get_tablet_set(DataDir* dir, CompactionType compaction_type);
@@ -378,6 +379,23 @@ public:
int64_t get_compaction_num_per_round() const { return
_compaction_num_per_round; }
+#ifdef BE_TEST
+ std::vector<TabletSharedPtr> generate_compaction_tasks_for_test(
+ CompactionType compaction_type, std::vector<DataDir*>& data_dirs,
bool check_score) {
+ auto tablet_contexts = _generate_compaction_tasks(compaction_type,
data_dirs, check_score);
+ std::vector<TabletSharedPtr> tablets;
+ tablets.reserve(tablet_contexts.size());
+ for (auto& context : tablet_contexts) {
+ tablets.emplace_back(std::move(context.tablet));
+ }
+ return tablets;
+ }
+
+ CompactionSubmitRegistry& compaction_submit_registry_for_test() {
+ return _compaction_submit_registry;
+ }
+#endif
+
private:
// Instance should be inited from `static open()`
// MUST NOT be called in other circumstances.
diff --git a/be/src/storage/tablet/tablet_manager.cpp
b/be/src/storage/tablet/tablet_manager.cpp
index cea5d672daa..dea24b37de6 100644
--- a/be/src/storage/tablet/tablet_manager.cpp
+++ b/be/src/storage/tablet/tablet_manager.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
#include <list>
#include <mutex>
+#include <optional>
#include <ostream>
#include <string_view>
@@ -43,6 +44,7 @@
#include "io/fs/local_file_system.h"
#include "runtime/exec_env.h"
#include "service/backend_options.h"
+#include "storage/compaction/cumulative_compaction_policy.h"
#include "storage/compaction/cumulative_compaction_time_series_policy.h"
#include "storage/data_dir.h"
#include "storage/olap_common.h"
@@ -730,9 +732,13 @@ struct TabletScore {
std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compaction(
CompactionType compaction_type, DataDir* data_dir,
- const std::unordered_set<TabletSharedPtr>&
tablet_submitted_compaction, uint32_t* score,
+ const std::unordered_set<TabletSharedPtr>& tablet_submitted_compaction,
+ CompactionScoreStats* score_stats,
const std::unordered_map<std::string_view,
std::shared_ptr<CumulativeCompactionPolicy>>&
all_cumulative_compaction_policies) {
+ DCHECK(score_stats != nullptr);
+ *score_stats = {};
+ score_stats->scanned = true;
int64_t now_ms = UnixMillis();
const string& compaction_type_str = compaction_type ==
CompactionType::BASE_COMPACTION ? "base"
: compaction_type ==
CompactionType::CUMU_BINLOG_COMPACTION
@@ -793,8 +799,9 @@ std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compact
return;
}
}
- auto cumulative_compaction_policy =
all_cumulative_compaction_policies.at(
- tablet_ptr->tablet_meta()->compaction_policy());
+ const auto& compaction_policy =
tablet_ptr->tablet_meta()->compaction_policy();
+ auto cumulative_compaction_policy =
+ all_cumulative_compaction_policies.at(compaction_policy);
uint32_t current_compaction_score =
tablet_ptr->calc_compaction_score(compaction_type);
if (current_compaction_score < 5) {
tablet_ptr->set_skip_compaction(true, compaction_type,
UnixSeconds());
@@ -804,6 +811,24 @@ std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compact
return;
}
+ std::optional<bool> suitable_for_compaction;
+ auto is_suitable = [&]() {
+ if (!suitable_for_compaction.has_value()) {
+ suitable_for_compaction = tablet_ptr->suitable_for_compaction(
+ compaction_type, cumulative_compaction_policy);
+ }
+ return suitable_for_compaction.value();
+ };
+
+ if (compaction_type == CompactionType::CUMULATIVE_COMPACTION) {
+ int64_t* policy_max_score = compaction_policy ==
CUMULATIVE_TIME_SERIES_POLICY
+ ?
&score_stats->time_series_max_score
+ :
&score_stats->size_based_max_score;
+ if (current_compaction_score > *policy_max_score && is_suitable())
{
+ *policy_max_score = current_compaction_score;
+ }
+ }
+
if (compaction_num_per_round > 1) {
TabletScore ts;
ts.score = current_compaction_score;
@@ -811,9 +836,7 @@ std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compact
if ((top_tablets.size() >= compaction_num_per_round &&
current_compaction_score > top_tablets.top().score) ||
top_tablets.size() < compaction_num_per_round) {
- bool ret = tablet_ptr->suitable_for_compaction(compaction_type,
-
cumulative_compaction_policy);
- if (ret) {
+ if (is_suitable()) {
top_tablets.push(ts);
if (top_tablets.size() > compaction_num_per_round) {
top_tablets.pop();
@@ -823,9 +846,7 @@ std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compact
}
} else {
if (current_compaction_score > highest_score) {
- bool ret = tablet_ptr->suitable_for_compaction(compaction_type,
-
cumulative_compaction_policy);
- if (ret) {
+ if (is_suitable()) {
highest_score = current_compaction_score;
best_tablet_context = {.tablet_ptr = tablet_ptr,
.score = current_compaction_score};
@@ -855,7 +876,7 @@ std::vector<TabletCompactionContext>
TabletManager::find_best_tablets_to_compact
picked_tablet_contexts.emplace_back(TabletCompactionContext {.tablet =
it->tablet_ptr});
}
- *score = highest_score;
+ score_stats->max_score = highest_score;
return picked_tablet_contexts;
}
diff --git a/be/src/storage/tablet/tablet_manager.h
b/be/src/storage/tablet/tablet_manager.h
index b507e79ada7..d1c6097cb42 100644
--- a/be/src/storage/tablet/tablet_manager.h
+++ b/be/src/storage/tablet/tablet_manager.h
@@ -82,7 +82,8 @@ public:
// single compaction tasks for the tablet.
std::vector<TabletCompactionContext> find_best_tablets_to_compaction(
CompactionType compaction_type, DataDir* data_dir,
- const std::unordered_set<TabletSharedPtr>&
tablet_submitted_compaction, uint32_t* score,
+ const std::unordered_set<TabletSharedPtr>&
tablet_submitted_compaction,
+ CompactionScoreStats* score_stats,
const std::unordered_map<std::string_view,
std::shared_ptr<CumulativeCompactionPolicy>>&
all_cumulative_compaction_policies);
diff --git a/be/test/cloud/cloud_compaction_test.cpp
b/be/test/cloud/cloud_compaction_test.cpp
index 0c21a845f59..78440a82de3 100644
--- a/be/test/cloud/cloud_compaction_test.cpp
+++ b/be/test/cloud/cloud_compaction_test.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <memory>
+#include <string_view>
#include "cloud/cloud_base_compaction.h"
#include "cloud/cloud_cluster_info.h"
@@ -29,8 +30,10 @@
#include "cloud/cloud_tablet.h"
#include "cloud/cloud_tablet_mgr.h"
#include "cloud/config.h"
+#include "common/metrics/doris_metrics.h"
#include "io/fs/s3_file_system.h"
#include "json2pb/json_to_pb.h"
+#include "storage/compaction/cumulative_compaction_time_series_policy.h"
#include "storage/olap_common.h"
#include "storage/rowset/rowset_factory.h"
#include "storage/rowset/rowset_meta.h"
@@ -145,13 +148,16 @@ TEST_F(CloudCompactionTest,
failure_base_compaction_tablet_sleep_test) {
tablet1->set_last_base_compaction_failure_time(0);
tablet1->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
tablet1->_approximate_num_rowsets = 10;
+ tablet1->_approximate_cumu_num_rowsets = 0;
mgr.put_tablet_for_UT(tablet1);
- int64_t max_score;
+ CompactionScoreStats score_stats;
std::vector<std::shared_ptr<CloudTablet>> tablets {};
Status st = mgr.get_topn_tablets_to_compact(1,
CompactionType::BASE_COMPACTION, filter_out,
- &tablets, &max_score);
+ &tablets, &score_stats);
ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 10);
ASSERT_EQ(tablets.size(), 1);
tablet1->set_last_base_compaction_failure_time(
@@ -159,8 +165,10 @@ TEST_F(CloudCompactionTest,
failure_base_compaction_tablet_sleep_test) {
std::chrono::system_clock::now().time_since_epoch())
.count());
st = mgr.get_topn_tablets_to_compact(1, CompactionType::BASE_COMPACTION,
filter_out, &tablets,
- &max_score);
+ &score_stats);
ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 10);
ASSERT_EQ(tablets.size(), 0);
}
@@ -186,11 +194,15 @@ TEST_F(CloudCompactionTest,
failure_cumu_compaction_tablet_sleep_test) {
tablet1->_approximate_cumu_num_deltas = 10;
mgr.put_tablet_for_UT(tablet1);
- int64_t max_score;
+ CompactionScoreStats score_stats;
std::vector<std::shared_ptr<CloudTablet>> tablets {};
Status st = mgr.get_topn_tablets_to_compact(1,
CompactionType::CUMULATIVE_COMPACTION,
- filter_out, &tablets,
&max_score);
+ filter_out, &tablets,
&score_stats);
ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 10);
+ ASSERT_EQ(score_stats.size_based_max_score, 10);
+ ASSERT_EQ(score_stats.time_series_max_score, 0);
ASSERT_EQ(tablets.size(), 1);
tablet1->set_last_cumu_compaction_failure_time(
@@ -198,8 +210,10 @@ TEST_F(CloudCompactionTest,
failure_cumu_compaction_tablet_sleep_test) {
std::chrono::system_clock::now().time_since_epoch())
.count());
st = mgr.get_topn_tablets_to_compact(1, CompactionType::BASE_COMPACTION,
filter_out, &tablets,
- &max_score);
+ &score_stats);
ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 0);
ASSERT_EQ(tablets.size(), 0);
}
@@ -223,15 +237,155 @@ TEST_F(CloudCompactionTest,
binlog_compaction_max_score_ignores_normal_tablets)
binlog_tablet->_approximate_cumu_num_deltas = 7;
mgr.put_tablet_for_UT(binlog_tablet);
- int64_t max_score = 0;
+ CompactionScoreStats score_stats;
std::vector<std::shared_ptr<CloudTablet>> tablets {};
Status st = mgr.get_topn_tablets_to_compact(1,
CompactionType::CUMU_BINLOG_COMPACTION,
- filter_out, &tablets,
&max_score);
+ filter_out, &tablets,
&score_stats);
ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
ASSERT_EQ(tablets.size(), 1);
EXPECT_EQ(tablets.front()->tablet_id(), binlog_tablet->tablet_id());
- EXPECT_EQ(max_score, 7);
+ EXPECT_EQ(score_stats.max_score, 7);
+ EXPECT_EQ(score_stats.size_based_max_score, 0);
+ EXPECT_EQ(score_stats.time_series_max_score, 0);
+}
+
+TEST_F(CloudCompactionTest, split_cumu_compaction_score_stats_before_filter) {
+ CloudTabletMgr mgr(_engine);
+
+ auto create_tablet = [this, &mgr](int64_t tablet_id, std::string_view
compaction_policy,
+ int64_t score) {
+ TabletMetaSharedPtr tablet_meta(new TabletMeta(*_tablet_meta));
+ tablet_meta->_tablet_id = tablet_id;
+ tablet_meta->set_compaction_policy(std::string(compaction_policy));
+ auto tablet = std::make_shared<CloudTablet>(_engine, tablet_meta);
+
tablet->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
+ tablet->_approximate_cumu_num_deltas = score;
+ mgr.put_tablet_for_UT(tablet);
+ return tablet;
+ };
+
+ create_tablet(10000, CUMULATIVE_SIZE_BASED_POLICY, 7);
+ create_tablet(10001, CUMULATIVE_TIME_SERIES_POLICY, 13);
+
+ auto filter_time_series = [](CloudTablet* t) { return t->tablet_id() ==
10001; };
+ CompactionScoreStats score_stats;
+ std::vector<std::shared_ptr<CloudTablet>> tablets;
+ Status st = mgr.get_topn_tablets_to_compact(1,
CompactionType::CUMULATIVE_COMPACTION,
+ filter_time_series, &tablets,
&score_stats);
+ ASSERT_EQ(st, Status::OK());
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 13);
+ ASSERT_EQ(score_stats.size_based_max_score, 7);
+ ASSERT_EQ(score_stats.time_series_max_score, 13);
+ ASSERT_EQ(tablets.size(), 1);
+ ASSERT_EQ(tablets[0]->tablet_id(), 10000);
+}
+
+TEST_F(CloudCompactionTest,
generate_cloud_compaction_tasks_updates_policy_metrics) {
+ CloudTabletMgr& mgr = _engine.tablet_mgr();
+ TabletMetaSharedPtr tablet_meta(new TabletMeta(*_tablet_meta));
+ tablet_meta->_tablet_id = 11000;
+
tablet_meta->set_compaction_policy(std::string(CUMULATIVE_SIZE_BASED_POLICY));
+ auto tablet = std::make_shared<CloudTablet>(_engine, tablet_meta);
+ tablet->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
+ tablet->_approximate_cumu_num_deltas = 7;
+ mgr.put_tablet_for_UT(tablet);
+
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ auto tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMULATIVE_COMPACTION, false);
+ ASSERT_EQ(tablets.size(), 1);
+ ASSERT_EQ(tablets[0]->tablet_id(), 11000);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 200);
+
+ tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMULATIVE_COMPACTION, true);
+ ASSERT_EQ(tablets.size(), 1);
+ ASSERT_EQ(tablets[0]->tablet_id(), 11000);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 0);
+
+ TabletMetaSharedPtr time_series_meta(new TabletMeta(*_tablet_meta));
+ time_series_meta->_tablet_id = 11001;
+
time_series_meta->set_compaction_policy(std::string(CUMULATIVE_TIME_SERIES_POLICY));
+ auto time_series = std::make_shared<CloudTablet>(_engine,
time_series_meta);
+
time_series->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
+ time_series->_approximate_cumu_num_deltas = 13;
+ mgr.put_tablet_for_UT(time_series);
+
+ tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMULATIVE_COMPACTION, true);
+ ASSERT_FALSE(tablets.empty());
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 13);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 13);
+}
+
+TEST_F(CloudCompactionTest,
generate_cloud_binlog_compaction_tasks_updates_only_binlog_metric) {
+ CloudTabletMgr& mgr = _engine.tablet_mgr();
+
+ auto normal_meta = std::make_shared<TabletMeta>(*_tablet_meta);
+ normal_meta->_tablet_id = 11002;
+ normal_meta->set_tablet_role(TabletRolePB::TABLET_ROLE_DATA);
+ auto normal_tablet = std::make_shared<CloudTablet>(_engine, normal_meta);
+
normal_tablet->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
+ normal_tablet->_approximate_cumu_num_deltas = 10;
+ mgr.put_tablet_for_UT(normal_tablet);
+
+ auto binlog_meta = std::make_shared<TabletMeta>(*_tablet_meta);
+ binlog_meta->_tablet_id = 11003;
+ binlog_meta->set_tablet_role(TabletRolePB::TABLET_ROLE_ROW_BINLOG);
+ auto binlog_tablet = std::make_shared<CloudTablet>(_engine, binlog_meta);
+
binlog_tablet->tablet_meta()->tablet_schema()->set_disable_auto_compaction(false);
+ binlog_tablet->_approximate_cumu_num_deltas = 7;
+ mgr.put_tablet_for_UT(binlog_tablet);
+
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(103);
+ metrics->tablet_binlog_max_compaction_score->set_value(104);
+
+ auto tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMU_BINLOG_COMPACTION, true);
+
+ ASSERT_EQ(tablets.size(), 1);
+ ASSERT_EQ(tablets[0]->tablet_id(), binlog_tablet->tablet_id());
+ ASSERT_EQ(metrics->tablet_binlog_max_compaction_score->value(), 7);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 101);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 102);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 103);
+}
+
+TEST_F(CloudCompactionTest,
generate_cloud_compaction_tasks_clears_metrics_without_tablets) {
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ auto tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMULATIVE_COMPACTION, false);
+ ASSERT_TRUE(tablets.empty());
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 101);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 102);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 200);
+
+ tablets = _engine.generate_cloud_compaction_tasks_for_test(
+ CompactionType::CUMULATIVE_COMPACTION, true);
+
+ ASSERT_TRUE(tablets.empty());
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 0);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 0);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 0);
}
static RowsetSharedPtr create_rowset(Version version, int num_segments, bool
overlapping,
diff --git a/be/test/storage/tablet/tablet_mgr_test.cpp
b/be/test/storage/tablet/tablet_mgr_test.cpp
index b3e15265fc9..d5e3dd1784b 100644
--- a/be/test/storage/tablet/tablet_mgr_test.cpp
+++ b/be/test/storage/tablet/tablet_mgr_test.cpp
@@ -26,9 +26,11 @@
#include <algorithm>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
#include "common/config.h"
+#include "common/metrics/doris_metrics.h"
#include "common/status.h"
#include "gtest/gtest_pred_impl.h"
#include "io/fs/local_file_system.h"
@@ -47,6 +49,8 @@
#include "storage/tablet/tablet_manager.h"
#include "storage/tablet/tablet_meta.h"
#include "storage/tablet/tablet_meta_manager.h"
+#include "util/debug_points.h"
+#include "util/defer_op.h"
#include "util/uid_util.h"
using ::testing::_;
@@ -88,6 +92,90 @@ public:
_tablet_mgr = nullptr;
config::compaction_num_per_round = 1;
}
+
+ TabletSharedPtr create_compaction_tablet(
+ int64_t tablet_id, int rowset_size,
+ std::string_view compaction_policy = CUMULATIVE_SIZE_BASED_POLICY,
+ DataDir* data_dir = nullptr) {
+ data_dir = data_dir == nullptr ? _data_dir : data_dir;
+ std::vector<TColumn> cols;
+ TColumn col1;
+ col1.column_type.type = TPrimitiveType::SMALLINT;
+ col1.__set_column_name("col1");
+ col1.__set_is_key(true);
+ cols.push_back(col1);
+
+ TColumn col2;
+ col2.column_type.type = TPrimitiveType::INT;
+ col2.__set_column_name(SEQUENCE_COL);
+ col2.__set_is_key(false);
+ col2.__set_aggregation_type(TAggregationType::REPLACE);
+ cols.push_back(col2);
+
+ TColumn col3;
+ col3.column_type.type = TPrimitiveType::INT;
+ col3.__set_column_name("v1");
+ col3.__set_is_key(false);
+ col3.__set_aggregation_type(TAggregationType::REPLACE);
+ cols.push_back(col3);
+
+ RuntimeProfile profile("CreateTablet");
+ TTabletSchema tablet_schema;
+ tablet_schema.__set_short_key_column_count(1);
+ tablet_schema.__set_schema_hash(3333);
+ tablet_schema.__set_keys_type(TKeysType::UNIQUE_KEYS);
+ tablet_schema.__set_storage_type(TStorageType::COLUMN);
+ tablet_schema.__set_columns(cols);
+ tablet_schema.__set_sequence_col_idx(1);
+ TCreateTabletReq create_tablet_req;
+ create_tablet_req.__set_tablet_schema(tablet_schema);
+ create_tablet_req.__set_tablet_id(tablet_id);
+ create_tablet_req.__set_version(1);
+ create_tablet_req.__set_replica_id(tablet_id * 10);
+
create_tablet_req.__set_compaction_policy(std::string(compaction_policy));
+ if (compaction_policy == CUMULATIVE_TIME_SERIES_POLICY) {
+
create_tablet_req.__set_time_series_compaction_file_count_threshold(1);
+ }
+ std::vector<DataDir*> data_dirs;
+ data_dirs.push_back(data_dir);
+ Status create_st = _tablet_mgr->create_tablet(create_tablet_req,
data_dirs, &profile);
+ if (!create_st.ok()) {
+ ADD_FAILURE() << create_st;
+ return nullptr;
+ }
+
+ TabletSharedPtr tablet = _tablet_mgr->get_tablet(tablet_id);
+ if (tablet == nullptr) {
+ ADD_FAILURE() << "failed to get tablet " << tablet_id;
+ return nullptr;
+ }
+
+ auto create_rowset = [=, this](int64_t start, int64_t end) {
+ auto rowset_meta = std::make_shared<RowsetMeta>();
+ Version version(start, end);
+ rowset_meta->set_version(version);
+ rowset_meta->set_tablet_id(tablet->tablet_id());
+ rowset_meta->set_tablet_uid(tablet->tablet_uid());
+ rowset_meta->set_rowset_id(k_engine->next_rowset_id());
+ return std::make_shared<BetaRowset>(tablet->tablet_schema(),
std::move(rowset_meta),
+ tablet->tablet_path());
+ };
+ auto st = tablet->init();
+ if (!st.ok()) {
+ ADD_FAILURE() << st;
+ return nullptr;
+ }
+ for (int i = 2; i <= rowset_size; ++i) {
+ auto rs = create_rowset(i, i);
+ st = tablet->add_inc_rowset(rs);
+ if (!st.ok()) {
+ ADD_FAILURE() << st;
+ return nullptr;
+ }
+ }
+ return tablet;
+ }
+
StorageEngine* k_engine;
private:
@@ -345,7 +433,8 @@ TEST_F(TabletMgrTest, GetRowsetId) {
}
TEST_F(TabletMgrTest, FindTabletWithCompact) {
- auto create_tablet = [this](int64_t tablet_id, int rowset_size) {
+ auto create_tablet = [this](int64_t tablet_id, int rowset_size,
+ std::string_view compaction_policy =
CUMULATIVE_SIZE_BASED_POLICY) {
std::vector<TColumn> cols;
TColumn col1;
col1.column_type.type = TPrimitiveType::SMALLINT;
@@ -380,6 +469,10 @@ TEST_F(TabletMgrTest, FindTabletWithCompact) {
create_tablet_req.__set_tablet_id(tablet_id);
create_tablet_req.__set_version(1);
create_tablet_req.__set_replica_id(tablet_id * 10);
+
create_tablet_req.__set_compaction_policy(std::string(compaction_policy));
+ if (compaction_policy == CUMULATIVE_TIME_SERIES_POLICY) {
+
create_tablet_req.__set_time_series_compaction_file_count_threshold(1);
+ }
std::vector<DataDir*> data_dirs;
data_dirs.push_back(_data_dir);
Status create_st = _tablet_mgr->create_tablet(create_tablet_req,
data_dirs, &profile);
@@ -433,20 +526,68 @@ TEST_F(TabletMgrTest, FindTabletWithCompact) {
cumulative_compaction_policies[CUMULATIVE_TIME_SERIES_POLICY] =
CumulativeCompactionPolicyFactory::create_cumulative_compaction_policy(
CUMULATIVE_TIME_SERIES_POLICY);
- uint32_t score = 0;
+ CompactionScoreStats score_stats;
auto compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
- CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set, &score,
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
cumulative_compaction_policies);
ASSERT_EQ(compact_tablets.size(), 1);
ASSERT_EQ(compact_tablets[0].tablet->tablet_id(), 10);
- ASSERT_EQ(score, 14);
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 14);
+ ASSERT_EQ(score_stats.size_based_max_score, 14);
+ ASSERT_EQ(score_stats.time_series_max_score, 0);
+
+ // create 10 more tablets with higher compaction scores
+ for (int64_t id = 11; id <= 20; ++id) {
+ create_tablet(id, rowset_size++);
+ }
+
+ compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
+ cumulative_compaction_policies);
+ ASSERT_EQ(compact_tablets.size(), 1);
+ ASSERT_EQ(compact_tablets[0].tablet->tablet_id(), 20);
+ ASSERT_EQ(score_stats.max_score, 24);
+ ASSERT_EQ(score_stats.size_based_max_score, 24);
+ ASSERT_EQ(score_stats.time_series_max_score, 0);
+
+ create_tablet(21, rowset_size++);
+
+ compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
+ cumulative_compaction_policies);
+ ASSERT_EQ(compact_tablets.size(), 1);
+ ASSERT_EQ(compact_tablets[0].tablet->tablet_id(), 21);
+ ASSERT_EQ(score_stats.max_score, 25);
+ ASSERT_EQ(score_stats.size_based_max_score, 25);
+ ASSERT_EQ(score_stats.time_series_max_score, 0);
// drop all tablets
- for (int64_t id = 1; id <= 10; ++id) {
+ for (int64_t id = 1; id <= 21; ++id) {
Status drop_st = _tablet_mgr->drop_tablet(id, id * 10, false);
ASSERT_TRUE(drop_st.ok()) << drop_st;
}
+ {
+ create_tablet(40001, 8, CUMULATIVE_SIZE_BASED_POLICY);
+ create_tablet(40002, 12, CUMULATIVE_TIME_SERIES_POLICY);
+
+ compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
+ cumulative_compaction_policies);
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 12);
+ ASSERT_EQ(score_stats.size_based_max_score, 8);
+ ASSERT_EQ(score_stats.time_series_max_score, 12);
+ ASSERT_EQ(compact_tablets.size(), 1);
+ ASSERT_EQ(compact_tablets[0].tablet->tablet_id(), 40002);
+
+ Status drop_st = _tablet_mgr->drop_tablet(40001, 400010, false);
+ ASSERT_TRUE(drop_st.ok()) << drop_st;
+ drop_st = _tablet_mgr->drop_tablet(40002, 400020, false);
+ ASSERT_TRUE(drop_st.ok()) << drop_st;
+ }
+
{
k_engine->_compaction_num_per_round = 10;
for (int64_t i = 1; i <= 100; ++i) {
@@ -454,7 +595,7 @@ TEST_F(TabletMgrTest, FindTabletWithCompact) {
}
compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
- CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score,
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
cumulative_compaction_policies);
ASSERT_EQ(compact_tablets.size(), 10);
int index = 0;
@@ -479,7 +620,7 @@ TEST_F(TabletMgrTest, FindTabletWithCompact) {
}
compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
- CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score,
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
cumulative_compaction_policies);
ASSERT_EQ(compact_tablets.size(), 5);
for (int i = 0; i < 5; ++i) {
@@ -501,6 +642,167 @@ TEST_F(TabletMgrTest, FindTabletWithCompact) {
ASSERT_TRUE(trash_st.ok()) << trash_st;
}
+TEST_F(TabletMgrTest, FindBestTabletsIgnoresUnsuitablePolicyScore) {
+ auto tablet = create_compaction_tablet(50001, 12,
CUMULATIVE_TIME_SERIES_POLICY);
+ ASSERT_TRUE(tablet != nullptr);
+
ASSERT_GT(tablet->calc_compaction_score(CompactionType::CUMULATIVE_COMPACTION),
5);
+
+ bool old_enable_debug_points = config::enable_debug_points;
+ config::enable_debug_points = true;
+ Defer restore_debug_points([&] { config::enable_debug_points =
old_enable_debug_points; });
+
DebugPoints::instance()->add("Tablet._calc_cumulative_compaction_score.return");
+ Defer clear_debug_point([] { DebugPoints::instance()->clear(); });
+
+ std::unordered_set<TabletSharedPtr> cumu_set;
+ std::unordered_map<std::string_view,
std::shared_ptr<CumulativeCompactionPolicy>>
+ cumulative_compaction_policies;
+ cumulative_compaction_policies[CUMULATIVE_SIZE_BASED_POLICY] =
+
CumulativeCompactionPolicyFactory::create_cumulative_compaction_policy(
+ CUMULATIVE_SIZE_BASED_POLICY);
+ cumulative_compaction_policies[CUMULATIVE_TIME_SERIES_POLICY] =
+
CumulativeCompactionPolicyFactory::create_cumulative_compaction_policy(
+ CUMULATIVE_TIME_SERIES_POLICY);
+
+ CompactionScoreStats score_stats;
+ auto compact_tablets = _tablet_mgr->find_best_tablets_to_compaction(
+ CompactionType::CUMULATIVE_COMPACTION, _data_dir, cumu_set,
&score_stats,
+ cumulative_compaction_policies);
+ ASSERT_TRUE(score_stats.scanned);
+ ASSERT_EQ(score_stats.max_score, 0);
+ ASSERT_EQ(score_stats.size_based_max_score, 0);
+ ASSERT_EQ(score_stats.time_series_max_score, 0);
+ ASSERT_TRUE(compact_tablets.empty());
+}
+
+TEST_F(TabletMgrTest, GenerateCompactionTasksClearsMissingPolicyScoreOnCheck) {
+ auto tablet = create_compaction_tablet(51001, 8,
CUMULATIVE_SIZE_BASED_POLICY);
+ ASSERT_TRUE(tablet != nullptr);
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ std::vector<DataDir*> data_dirs {_data_dir};
+ auto tasks =
k_engine->generate_compaction_tasks_for_test(CompactionType::CUMULATIVE_COMPACTION,
+ data_dirs, true);
+
+ ASSERT_EQ(tasks.size(), 1);
+ ASSERT_EQ(tasks[0]->tablet_id(), 51001);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 0);
+}
+
+TEST_F(TabletMgrTest,
GenerateCompactionTasksKeepsMissingPolicyScoreWithoutCheck) {
+ auto tablet = create_compaction_tablet(52001, 8,
CUMULATIVE_SIZE_BASED_POLICY);
+ ASSERT_TRUE(tablet != nullptr);
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ std::vector<DataDir*> data_dirs {_data_dir};
+ auto tasks =
k_engine->generate_compaction_tasks_for_test(CompactionType::CUMULATIVE_COMPACTION,
+ data_dirs,
false);
+
+ ASSERT_EQ(tasks.size(), 1);
+ ASSERT_EQ(tasks[0]->tablet_id(), 52001);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 200);
+}
+
+TEST_F(TabletMgrTest,
GenerateCompactionTasksDoesNotUpdateMetricWhenNoDirScanned) {
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(101);
+ metrics->tablet_size_based_max_compaction_score->set_value(102);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ std::vector<DataDir*> data_dirs;
+ auto tasks =
k_engine->generate_compaction_tasks_for_test(CompactionType::CUMULATIVE_COMPACTION,
+ data_dirs, true);
+
+ ASSERT_TRUE(tasks.empty());
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 101);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 102);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 200);
+}
+
+TEST_F(TabletMgrTest, GenerateCompactionTasksAggregatesScoreWhenNoSlot) {
+ auto dummy = create_compaction_tablet(53000, 5,
CUMULATIVE_SIZE_BASED_POLICY);
+ auto size_based = create_compaction_tablet(53001, 8,
CUMULATIVE_SIZE_BASED_POLICY);
+ auto time_series = create_compaction_tablet(53002, 12,
CUMULATIVE_TIME_SERIES_POLICY);
+ ASSERT_TRUE(dummy != nullptr);
+ ASSERT_TRUE(size_based != nullptr);
+ ASSERT_TRUE(time_series != nullptr);
+
+ std::vector<DataDir*> data_dirs {_data_dir};
+ auto& registry = k_engine->compaction_submit_registry_for_test();
+ registry.reset(data_dirs);
+ Defer reset_registry([&] { registry.reset(data_dirs); });
+ dummy->compaction_stage = CompactionStage::EXECUTING;
+ ASSERT_FALSE(registry.insert(dummy,
CompactionType::CUMULATIVE_COMPACTION));
+
+ int32_t old_compaction_task_num_per_disk =
config::compaction_task_num_per_disk;
+ config::compaction_task_num_per_disk = 1;
+ Defer restore_config(
+ [&] { config::compaction_task_num_per_disk =
old_compaction_task_num_per_disk; });
+ bool old_enable_compaction_priority_scheduling =
config::enable_compaction_priority_scheduling;
+ config::enable_compaction_priority_scheduling = false;
+ Defer restore_priority_scheduling([&] {
+ config::enable_compaction_priority_scheduling =
old_enable_compaction_priority_scheduling;
+ });
+
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(0);
+ metrics->tablet_size_based_max_compaction_score->set_value(0);
+ metrics->tablet_time_series_max_compaction_score->set_value(0);
+
+ auto tasks =
k_engine->generate_compaction_tasks_for_test(CompactionType::CUMULATIVE_COMPACTION,
+ data_dirs, true);
+
+ ASSERT_TRUE(tasks.empty());
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 12);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 12);
+}
+
+TEST_F(TabletMgrTest,
GenerateCompactionTasksDoesNotLowerPolicyScoreWhenDirFull) {
+ std::string full_dir_path =
"./be/test/storage/test_data/converter_test_data/tmp_full";
+
ASSERT_TRUE(io::global_local_filesystem()->delete_directory(full_dir_path).ok());
+
ASSERT_TRUE(io::global_local_filesystem()->create_directory(full_dir_path).ok());
+ ASSERT_TRUE(io::global_local_filesystem()->create_directory(full_dir_path
+ "/meta").ok());
+ Defer cleanup_full_dir([&] {
+
static_cast<void>(io::global_local_filesystem()->delete_directory(full_dir_path));
+ });
+
+ auto full_data_dir = std::make_unique<DataDir>(*k_engine, full_dir_path,
1000000000);
+ ASSERT_TRUE(full_data_dir->init().ok());
+ auto full_time_series =
+ create_compaction_tablet(54001, 12, CUMULATIVE_TIME_SERIES_POLICY,
full_data_dir.get());
+ auto size_based = create_compaction_tablet(54002, 8,
CUMULATIVE_SIZE_BASED_POLICY);
+ ASSERT_TRUE(full_time_series != nullptr);
+ ASSERT_TRUE(size_based != nullptr);
+ Defer drop_full_tablet(
+ [&] { static_cast<void>(_tablet_mgr->drop_tablet(54001, 540010,
false)); });
+ full_data_dir->set_capacity_for_test(100, 0);
+
+ auto* metrics = DorisMetrics::instance();
+ metrics->tablet_cumulative_max_compaction_score->set_value(200);
+ metrics->tablet_size_based_max_compaction_score->set_value(0);
+ metrics->tablet_time_series_max_compaction_score->set_value(200);
+
+ std::vector<DataDir*> data_dirs {_data_dir, full_data_dir.get()};
+ auto tasks =
k_engine->generate_compaction_tasks_for_test(CompactionType::CUMULATIVE_COMPACTION,
+ data_dirs, true);
+
+ ASSERT_EQ(tasks.size(), 1);
+ ASSERT_EQ(tasks[0]->tablet_id(), 54002);
+ ASSERT_EQ(metrics->tablet_cumulative_max_compaction_score->value(), 200);
+ ASSERT_EQ(metrics->tablet_size_based_max_compaction_score->value(), 8);
+ ASSERT_EQ(metrics->tablet_time_series_max_compaction_score->value(), 200);
+}
+
TEST_F(TabletMgrTest, LoadTabletFromMeta) {
TTabletId tablet_id = 111;
TSchemaHash schema_hash = 3333;
diff --git a/be/test/util/doris_metrics_test.cpp
b/be/test/util/doris_metrics_test.cpp
index dfac2d557fe..a3269c9b04f 100644
--- a/be/test/util/doris_metrics_test.cpp
+++ b/be/test/util/doris_metrics_test.cpp
@@ -178,6 +178,18 @@ TEST_F(DorisMetricsTest, Normal) {
EXPECT_TRUE(metric != nullptr);
EXPECT_STREQ("31", metric->to_string().c_str());
}
+ {
+
DorisMetrics::instance()->tablet_size_based_max_compaction_score->set_value(41);
+ auto metric =
server_entity->get_metric("tablet_size_based_max_compaction_score");
+ EXPECT_TRUE(metric != nullptr);
+ EXPECT_STREQ("41", metric->to_string().c_str());
+ }
+ {
+
DorisMetrics::instance()->tablet_time_series_max_compaction_score->set_value(42);
+ auto metric =
server_entity->get_metric("tablet_time_series_max_compaction_score");
+ EXPECT_TRUE(metric != nullptr);
+ EXPECT_STREQ("42", metric->to_string().c_str());
+ }
{
DorisMetrics::instance()->base_compaction_bytes_total->increment(32);
auto metric =
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]