be/src/cloud/cloud_cumulative_compaction_binlog_policy.cpp
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "cloud/cloud_cumulative_compaction_binlog_policy.h" |
19 | | |
20 | | #include "cloud/cloud_tablet.h" |
21 | | #include "common/config.h" |
22 | | #include "storage/compaction/cumulative_compaction_binlog_policy.h" |
23 | | #include "storage/tablet/tablet.h" |
24 | | #include "util/time.h" |
25 | | |
26 | | namespace doris { |
27 | | |
28 | | bool CloudBinlogCumulativeCompactionPolicy::is_compaction_enough( |
29 | 2 | const RowsetMetaSharedPtr& rowset_meta) const { |
30 | 2 | if (rowset_meta->compaction_level() != |
31 | 2 | BinlogCumulativeCompactionPolicy::kBinlogCompactionMaxLevel - 1) { |
32 | 0 | return false; |
33 | 0 | } |
34 | 2 | if (rowset_meta->start_version() == 0) { |
35 | 0 | return true; |
36 | 0 | } |
37 | 2 | return rowset_meta->data_disk_size() >= |
38 | 2 | config::binlog_compaction_goal_size_mbytes * 1024 * 1024 || |
39 | 2 | rowset_meta->get_compaction_score() >= config::binlog_compaction_file_count_threshold; |
40 | 2 | } |
41 | | |
42 | | int64_t CloudBinlogCumulativeCompactionPolicy::new_cumulative_point( |
43 | | CloudTablet* tablet, const RowsetSharedPtr& output_rowset, Version& last_delete_version, |
44 | 3 | int64_t last_cumulative_point) { |
45 | 3 | if (output_rowset->num_segments() == 0 || !is_compaction_enough(output_rowset->rowset_meta())) { |
46 | 2 | return last_cumulative_point; |
47 | 2 | } |
48 | 1 | return output_rowset->end_version() + 1; |
49 | 3 | } |
50 | | |
51 | | int64_t CloudBinlogCumulativeCompactionPolicy::get_compaction_level( |
52 | | CloudTablet* tablet, const std::vector<RowsetSharedPtr>& input_rowsets, |
53 | 0 | RowsetSharedPtr output_rowset) { |
54 | 0 | DCHECK(!input_rowsets.empty()) << "tablet=" << tablet->tablet_id(); |
55 | 0 | int64_t first_level = input_rowsets.front()->rowset_meta()->compaction_level(); |
56 | 0 | for (size_t i = 1; i < input_rowsets.size(); ++i) { |
57 | 0 | DCHECK_EQ(first_level, input_rowsets[i]->rowset_meta()->compaction_level()) |
58 | 0 | << "tablet=" << tablet->tablet_id(); |
59 | 0 | DCHECK_EQ(input_rowsets[i]->start_version(), input_rowsets[i - 1]->end_version() + 1) |
60 | 0 | << "tablet=" << tablet->tablet_id(); |
61 | 0 | } |
62 | |
|
63 | 0 | if (first_level == BinlogCumulativeCompactionPolicy::kBinlogCompactionMaxLevel - 1) { |
64 | 0 | return first_level; |
65 | 0 | } |
66 | 0 | return first_level + 1; |
67 | 0 | } |
68 | | |
69 | | uint32_t CloudBinlogCumulativeCompactionPolicy::calc_binlog_compaction_level_score( |
70 | | CloudTablet* tablet, const std::vector<RowsetSharedPtr>& candidate_rowsets, |
71 | 15 | int8_t level) const { |
72 | 15 | uint32_t score = 0; |
73 | 15 | const int64_t point = tablet->cumulative_layer_point(); |
74 | 45 | for (const auto& rs : candidate_rowsets) { |
75 | 45 | auto rs_meta = rs->rowset_meta(); |
76 | 45 | if (rs_meta->compaction_level() != level) { |
77 | 30 | continue; |
78 | 30 | } |
79 | 15 | if (level == BinlogCumulativeCompactionPolicy::kBinlogCompactionMaxLevel - 1 && |
80 | 15 | point != Tablet::K_INVALID_CUMULATIVE_POINT && rs_meta->end_version() < point) { |
81 | 2 | score += 1; |
82 | 2 | continue; |
83 | 2 | } |
84 | 13 | score += rs_meta->get_compaction_score(); |
85 | 13 | } |
86 | 15 | return score; |
87 | 15 | } |
88 | | |
89 | | uint32_t CloudBinlogCumulativeCompactionPolicy::calc_binlog_compaction_score( |
90 | | CloudTablet* tablet, const std::vector<RowsetSharedPtr>& candidate_rowsets, |
91 | 5 | int8_t* compaction_level) const { |
92 | 5 | uint32_t max_score = 0; |
93 | 5 | int8_t max_level = -1; |
94 | 20 | for (int8_t level = 0; level < BinlogCumulativeCompactionPolicy::kBinlogCompactionMaxLevel; |
95 | 15 | ++level) { |
96 | 15 | uint32_t score = calc_binlog_compaction_level_score(tablet, candidate_rowsets, level); |
97 | 15 | if (score > max_score) { |
98 | 6 | max_score = score; |
99 | 6 | max_level = level; |
100 | 6 | } |
101 | 15 | } |
102 | 5 | if (compaction_level != nullptr) { |
103 | 5 | *compaction_level = max_level; |
104 | 5 | } |
105 | 5 | return max_score; |
106 | 5 | } |
107 | | |
108 | | void CloudBinlogCumulativeCompactionPolicy::filter_new_visible_rowsets( |
109 | | const std::vector<RowsetSharedPtr>& candidate_rowsets, |
110 | 5 | std::vector<RowsetSharedPtr>* output_rowsets) const { |
111 | 5 | output_rowsets->clear(); |
112 | 5 | int64_t now = UnixSeconds(); |
113 | 5 | int64_t max_processable_old_version = 0; |
114 | 5 | bool filter_new_rowset = |
115 | 5 | candidate_rowsets.size() <= config::binlog_compaction_file_count_threshold; |
116 | 18 | for (const auto& rs : candidate_rowsets) { |
117 | 18 | if (filter_new_rowset && rs->rowset_meta()->is_singleton_delta() && |
118 | 18 | rs->rowset_meta()->newest_write_timestamp() + |
119 | 6 | config::binlog_compaction_wait_timesec_after_visible > |
120 | 6 | now) { |
121 | 3 | continue; |
122 | 3 | } |
123 | 15 | max_processable_old_version = std::max(max_processable_old_version, rs->end_version()); |
124 | 15 | } |
125 | | |
126 | 5 | output_rowsets->reserve(candidate_rowsets.size()); |
127 | 18 | for (const auto& rs : candidate_rowsets) { |
128 | 18 | if (rs->start_version() <= max_processable_old_version) { |
129 | 15 | output_rowsets->push_back(rs); |
130 | 15 | } |
131 | 18 | } |
132 | 5 | } |
133 | | |
134 | | int64_t CloudBinlogCumulativeCompactionPolicy::pick_input_rowsets( |
135 | | CloudTablet* tablet, const std::vector<RowsetSharedPtr>& candidate_rowsets, |
136 | | const int64_t max_compaction_score, const int64_t min_compaction_score, |
137 | | std::vector<RowsetSharedPtr>* input_rowsets, Version* last_delete_version, |
138 | 5 | size_t* compaction_score, bool allow_delete) { |
139 | 5 | std::vector<RowsetSharedPtr> filtered_rowsets; |
140 | 5 | filter_new_visible_rowsets(candidate_rowsets, &filtered_rowsets); |
141 | | |
142 | 5 | int8_t compaction_level = -1; |
143 | 5 | calc_binlog_compaction_score(tablet, filtered_rowsets, &compaction_level); |
144 | 5 | if (compaction_level < 0) { |
145 | 0 | *compaction_score = 0; |
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | 5 | std::vector<RowsetSharedPtr> level_rowsets; |
150 | 5 | level_rowsets.reserve(filtered_rowsets.size()); |
151 | 15 | for (const auto& rs : filtered_rowsets) { |
152 | 15 | if (rs->rowset_meta()->compaction_level() != compaction_level) { |
153 | 2 | continue; |
154 | 2 | } |
155 | 13 | if (!level_rowsets.empty() && |
156 | 13 | rs->start_version() != level_rowsets.back()->end_version() + 1) { |
157 | 0 | LOG(WARNING) << "rowset is non-continuous in the same compaction_level " |
158 | 0 | "of binlog compaction. tablet=" |
159 | 0 | << tablet->tablet_id() |
160 | 0 | << ", compaction_level=" << static_cast<int>(compaction_level) |
161 | 0 | << ", prev_version=" << level_rowsets.back()->version() |
162 | 0 | << ", next_version=" << rs->version(); |
163 | 0 | *compaction_score = 0; |
164 | 0 | return 0; |
165 | 0 | } |
166 | 13 | level_rowsets.push_back(rs); |
167 | 13 | } |
168 | | |
169 | 5 | std::vector<RowsetSharedPtr> remaining_rowsets; |
170 | 5 | remaining_rowsets.reserve(level_rowsets.size()); |
171 | 5 | const int64_t point = tablet->cumulative_layer_point(); |
172 | 13 | for (const auto& rs : level_rowsets) { |
173 | 13 | if (compaction_level == BinlogCumulativeCompactionPolicy::kBinlogCompactionMaxLevel - 1 && |
174 | 13 | point != Tablet::K_INVALID_CUMULATIVE_POINT && rs->end_version() < point) { |
175 | 2 | continue; |
176 | 2 | } |
177 | 11 | remaining_rowsets.push_back(rs); |
178 | 11 | } |
179 | | |
180 | 5 | std::vector<RowsetSharedPtr> picked_rowsets; |
181 | 5 | picked_rowsets.reserve(remaining_rowsets.size()); |
182 | 5 | int transient_size = 0; |
183 | 5 | int64_t total_size = 0; |
184 | 5 | int64_t picked_score = 0; |
185 | 11 | for (const auto& rs : remaining_rowsets) { |
186 | 11 | if (transient_size >= max_compaction_score) { |
187 | 0 | break; |
188 | 0 | } |
189 | 11 | picked_rowsets.push_back(rs); |
190 | 11 | ++transient_size; |
191 | 11 | total_size += rs->data_disk_size(); |
192 | 11 | picked_score += rs->rowset_meta()->get_compaction_score(); |
193 | 11 | } |
194 | | |
195 | 5 | bool can_do_binlog_compaction = |
196 | 5 | total_size >= config::binlog_compaction_goal_size_mbytes * 1024 * 1024 || |
197 | 5 | picked_score >= config::binlog_compaction_file_count_threshold || |
198 | 5 | (UnixMillis() - tablet->last_cumu_compaction_success_time()) / 1000 >= |
199 | 1 | config::binlog_compaction_time_threshold_seconds; |
200 | 5 | if (transient_size < 2) { |
201 | 1 | can_do_binlog_compaction = false; |
202 | 1 | } |
203 | 5 | if (can_do_binlog_compaction) { |
204 | 4 | input_rowsets->swap(picked_rowsets); |
205 | 4 | *compaction_score = picked_score; |
206 | 4 | return transient_size; |
207 | 4 | } |
208 | | |
209 | 1 | input_rowsets->clear(); |
210 | 1 | *compaction_score = 0; |
211 | 1 | return 0; |
212 | 5 | } |
213 | | |
214 | | } // namespace doris |