Skip to content

Commit 5f75f9b

Browse files
authored
feat(storage): sepearte intra picker (risingwavelabs#12147)
1 parent f1672f7 commit 5f75f9b

File tree

5 files changed

+768
-569
lines changed

5 files changed

+768
-569
lines changed

src/meta/src/hummock/compaction/level_selector.rs

Lines changed: 90 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use risingwave_pb::hummock::hummock_version::Levels;
2626
use risingwave_pb::hummock::{compact_task, CompactionConfig, LevelType};
2727

2828
use super::picker::{
29-
CompactionTaskValidator, SpaceReclaimCompactionPicker, SpaceReclaimPickerState, TtlPickerState,
30-
TtlReclaimCompactionPicker,
29+
CompactionTaskValidator, IntraCompactionPicker, SpaceReclaimCompactionPicker,
30+
SpaceReclaimPickerState, TtlPickerState, TtlReclaimCompactionPicker,
3131
};
3232
use super::{
3333
create_compaction_task, LevelCompactionPicker, ManualCompactionOption, ManualCompactionPicker,
@@ -44,6 +44,23 @@ use crate::rpc::metrics::MetaMetrics;
4444

4545
pub const SCORE_BASE: u64 = 100;
4646

47+
#[derive(Debug, Default, Clone)]
48+
pub enum PickerType {
49+
Tier,
50+
Intra,
51+
ToBase,
52+
#[default]
53+
BottomLevel,
54+
}
55+
56+
#[derive(Default, Debug)]
57+
pub struct PickerInfo {
58+
score: u64,
59+
select_level: usize,
60+
target_level: usize,
61+
picker_type: PickerType,
62+
}
63+
4764
pub trait LevelSelector: Sync + Send {
4865
fn pick_compaction(
4966
&mut self,
@@ -71,7 +88,7 @@ pub struct SelectContext {
7188
// size of the files in `base_level` reaches its capacity, we will place data in a higher
7289
// level, which equals to `base_level -= 1;`.
7390
pub base_level: usize,
74-
pub score_levels: Vec<(u64, usize, usize)>,
91+
pub score_levels: Vec<PickerInfo>,
7592
}
7693

7794
pub struct DynamicLevelSelectorCore {
@@ -92,33 +109,34 @@ impl DynamicLevelSelectorCore {
92109

93110
fn create_compaction_picker(
94111
&self,
95-
select_level: usize,
96-
target_level: usize,
112+
picker_info: &PickerInfo,
97113
overlap_strategy: Arc<dyn OverlapStrategy>,
98114
compaction_task_validator: Arc<CompactionTaskValidator>,
99115
) -> Box<dyn CompactionPicker> {
100-
if select_level == 0 {
101-
if target_level == 0 {
102-
Box::new(TierCompactionPicker::new_with_validator(
103-
self.config.clone(),
104-
compaction_task_validator,
105-
))
106-
} else {
107-
Box::new(LevelCompactionPicker::new_with_validator(
108-
target_level,
109-
self.config.clone(),
110-
compaction_task_validator,
116+
match picker_info.picker_type {
117+
PickerType::Tier => Box::new(TierCompactionPicker::new_with_validator(
118+
self.config.clone(),
119+
compaction_task_validator,
120+
)),
121+
PickerType::ToBase => Box::new(LevelCompactionPicker::new_with_validator(
122+
picker_info.target_level,
123+
self.config.clone(),
124+
compaction_task_validator,
125+
)),
126+
PickerType::Intra => Box::new(IntraCompactionPicker::new_with_validator(
127+
self.config.clone(),
128+
compaction_task_validator,
129+
)),
130+
PickerType::BottomLevel => {
131+
assert_eq!(picker_info.select_level + 1, picker_info.target_level);
132+
Box::new(MinOverlappingPicker::new(
133+
picker_info.select_level,
134+
picker_info.target_level,
135+
self.config.max_bytes_for_level_base,
136+
self.config.split_by_state_table,
137+
overlap_strategy,
111138
))
112139
}
113-
} else {
114-
assert_eq!(select_level + 1, target_level);
115-
Box::new(MinOverlappingPicker::new(
116-
select_level,
117-
target_level,
118-
self.config.max_bytes_for_level_base,
119-
self.config.split_by_state_table,
120-
overlap_strategy,
121-
))
122140
}
123141
}
124142

@@ -217,8 +235,12 @@ impl DynamicLevelSelectorCore {
217235
std::cmp::min(idle_file_count, overlapping_file_count) as u64 * SCORE_BASE
218236
/ self.config.level0_tier_compact_file_number;
219237
// Reduce the level num of l0 overlapping sub_level
220-
ctx.score_levels
221-
.push((std::cmp::max(l0_overlapping_score, SCORE_BASE + 1), 0, 0));
238+
ctx.score_levels.push(PickerInfo {
239+
score: std::cmp::max(l0_overlapping_score, SCORE_BASE + 1),
240+
select_level: 0,
241+
target_level: 0,
242+
picker_type: PickerType::Tier,
243+
})
222244
}
223245

224246
// The read query at the non-overlapping level only selects ssts that match the query
@@ -254,8 +276,24 @@ impl DynamicLevelSelectorCore {
254276
};
255277

256278
// Reduce the level num of l0 non-overlapping sub_level
257-
ctx.score_levels
258-
.push((non_overlapping_score, 0, ctx.base_level));
279+
ctx.score_levels.push({
280+
PickerInfo {
281+
score: non_overlapping_score,
282+
select_level: 0,
283+
target_level: ctx.base_level,
284+
picker_type: PickerType::ToBase,
285+
}
286+
});
287+
288+
// FIXME: more accurate score calculation algorithm will be introduced (#11903)
289+
ctx.score_levels.push({
290+
PickerInfo {
291+
score: non_overlapping_score,
292+
select_level: 0,
293+
target_level: 0,
294+
picker_type: PickerType::Intra,
295+
}
296+
});
259297
}
260298

261299
// The bottommost level can not be input level.
@@ -275,16 +313,23 @@ impl DynamicLevelSelectorCore {
275313
if total_size == 0 {
276314
continue;
277315
}
278-
ctx.score_levels.push((
279-
total_size * SCORE_BASE / ctx.level_max_bytes[level_idx],
280-
level_idx,
281-
level_idx + 1,
282-
));
316+
317+
ctx.score_levels.push({
318+
PickerInfo {
319+
score: total_size * SCORE_BASE / ctx.level_max_bytes[level_idx],
320+
select_level: level_idx,
321+
target_level: level_idx + 1,
322+
picker_type: PickerType::BottomLevel,
323+
}
324+
});
283325
}
284326

285327
// sort reverse to pick the largest one.
286-
ctx.score_levels
287-
.sort_by(|a, b| b.0.cmp(&a.0).then_with(|| a.2.cmp(&b.2)));
328+
ctx.score_levels.sort_by(|a, b| {
329+
b.score
330+
.cmp(&a.score)
331+
.then_with(|| a.target_level.cmp(&b.target_level))
332+
});
288333
ctx
289334
}
290335

@@ -379,21 +424,20 @@ impl LevelSelector for DynamicLevelSelector {
379424
let overlap_strategy =
380425
create_overlap_strategy(compaction_group.compaction_config.compaction_mode());
381426
let ctx = dynamic_level_core.get_priority_levels(levels, level_handlers);
382-
383427
// TODO: Determine which rule to enable by write limit
384428
let compaction_task_validator = Arc::new(CompactionTaskValidator::new(
385429
compaction_group.compaction_config.clone(),
386430
));
387-
for (score, select_level, target_level) in ctx.score_levels {
388-
if score <= SCORE_BASE {
431+
for picker_info in &ctx.score_levels {
432+
if picker_info.score <= SCORE_BASE {
389433
return None;
390434
}
391435
let mut picker = dynamic_level_core.create_compaction_picker(
392-
select_level,
393-
target_level,
436+
picker_info,
394437
overlap_strategy.clone(),
395438
compaction_task_validator.clone(),
396439
);
440+
397441
let mut stats = LocalPickerStatistic::default();
398442
if let Some(ret) = picker.pick_compaction(levels, level_handlers, &mut stats) {
399443
ret.add_pending_task(task_id, level_handlers);
@@ -404,9 +448,11 @@ impl LevelSelector for DynamicLevelSelector {
404448
self.task_type(),
405449
));
406450
}
407-
selector_stats
408-
.skip_picker
409-
.push((select_level, target_level, stats));
451+
selector_stats.skip_picker.push((
452+
picker_info.select_level,
453+
picker_info.target_level,
454+
stats,
455+
));
410456
}
411457
None
412458
}

0 commit comments

Comments
 (0)