@@ -43,6 +43,9 @@ use databend_common_metrics::storage::*;
43
43
use databend_common_sql:: evaluator:: BlockOperator ;
44
44
use databend_common_sql:: executor:: physical_plans:: OnConflictField ;
45
45
use databend_common_sql:: StreamContext ;
46
+ use databend_storages_common_cache:: BlockMetaCache ;
47
+ use databend_storages_common_cache:: CacheAccessor ;
48
+ use databend_storages_common_cache:: CacheManager ;
46
49
use databend_storages_common_cache:: LoadParams ;
47
50
use databend_storages_common_index:: filters:: Filter ;
48
51
use databend_storages_common_index:: filters:: Xor8Filter ;
@@ -100,6 +103,8 @@ struct AggregationContext {
100
103
io_request_semaphore : Arc < Semaphore > ,
101
104
// generate stream columns if necessary
102
105
stream_ctx : Option < StreamContext > ,
106
+
107
+ block_meta_cache : Option < BlockMetaCache > ,
103
108
}
104
109
105
110
// Apply MergeIntoOperations to segments
@@ -209,6 +214,7 @@ impl ReplaceIntoOperationAggregator {
209
214
block_builder,
210
215
io_request_semaphore,
211
216
stream_ctx,
217
+ block_meta_cache : CacheManager :: instance ( ) . get_block_meta_cache ( ) ,
212
218
} ) ,
213
219
} )
214
220
}
@@ -291,6 +297,8 @@ impl ReplaceIntoOperationAggregator {
291
297
impl ReplaceIntoOperationAggregator {
292
298
#[ async_backtrace:: framed]
293
299
pub async fn apply ( & mut self ) -> Result < Option < MutationLogs > > {
300
+ let block_meta_cache = & self . aggregation_ctx . block_meta_cache ;
301
+
294
302
metrics_inc_replace_number_apply_deletion ( ) ;
295
303
296
304
// track number of segments and blocks after pruning (per merge action application)
@@ -317,7 +325,7 @@ impl ReplaceIntoOperationAggregator {
317
325
let mut mutation_log_handlers = Vec :: new ( ) ;
318
326
let mut num_rows_mutated = 0 ;
319
327
for ( segment_idx, block_deletion) in self . deletion_accumulator . deletions . drain ( ) {
320
- let ( path , ver) = self
328
+ let ( segment_path , ver) = self
321
329
. aggregation_ctx
322
330
. segment_locations
323
331
. get ( & segment_idx)
@@ -329,19 +337,41 @@ impl ReplaceIntoOperationAggregator {
329
337
} ) ?;
330
338
331
339
let load_param = LoadParams {
332
- location : path . clone ( ) ,
340
+ location : segment_path . clone ( ) ,
333
341
len_hint : None ,
334
342
ver : * ver,
335
343
put_cache : true ,
336
344
} ;
337
345
338
- let compact_segment_info = aggregation_ctx . segment_reader . read ( & load_param ) . await ? ;
339
- let segment_info : SegmentInfo = compact_segment_info . try_into ( ) ? ;
346
+ // Retain SegmentInfo to avoid repeatedly extracting it from CompactSegmentInfo later.
347
+ let mut opt_segment_info : Option < SegmentInfo > = None ;
340
348
341
349
for ( block_index, keys) in block_deletion {
350
+ let block_cache_key = format ! ( "{segment_path}-{block_index}" ) ;
351
+ let block_meta = match block_meta_cache. get ( & block_cache_key) {
352
+ Some ( block_meta) => block_meta,
353
+ None => {
354
+ let block_meta = if let Some ( segment_info) = & opt_segment_info {
355
+ segment_info. blocks [ block_index] . clone ( )
356
+ } else {
357
+ let compact_segment_info =
358
+ aggregation_ctx. segment_reader . read ( & load_param) . await ?;
359
+ let segment_info: SegmentInfo = compact_segment_info. try_into ( ) ?;
360
+ let block_meta = segment_info. blocks [ block_index] . clone ( ) ;
361
+ opt_segment_info = Some ( segment_info) ;
362
+ block_meta
363
+ } ;
364
+ // A query node typically processes only a subset of the BlockMeta in a given segment.
365
+ // Therefore, even though all BlockMeta of a segment are available here, not all are populated into the cache.
366
+ block_meta_cache. insert ( block_cache_key, block_meta. as_ref ( ) . clone ( ) ) ;
367
+ block_meta
368
+ }
369
+ } ;
370
+
342
371
let permit =
343
372
acquire_task_permit ( aggregation_ctx. io_request_semaphore . clone ( ) ) . await ?;
344
- let block_meta = segment_info. blocks [ block_index] . clone ( ) ;
373
+
374
+ // let block_meta = segment_info.blocks[block_index].clone();
345
375
let aggregation_ctx = aggregation_ctx. clone ( ) ;
346
376
num_rows_mutated += block_meta. row_count ;
347
377
// self.aggregation_ctx.
@@ -604,7 +634,7 @@ impl AggregationContext {
604
634
if let Some ( stats) = column_stats {
605
635
let max = stats. max ( ) ;
606
636
let min = stats. min ( ) ;
607
- std:: cmp:: min ( key_max, max) >= std:: cmp:: max ( key_min, min)
637
+ std:: cmp:: min ( key_max, max) >= std:: cmp:: max ( key_min, min)
608
638
|| // coincide overlap
609
639
( max == key_max && min == key_min)
610
640
} else {
@@ -630,22 +660,22 @@ impl AggregationContext {
630
660
let reader = reader. clone ( ) ;
631
661
GlobalIORuntime :: instance ( )
632
662
. spawn ( async move {
633
- let column_chunks = merged_io_read_result. columns_chunks ( ) ?;
634
- reader. deserialize_chunks (
635
- block_meta_ptr. location . 0 . as_str ( ) ,
636
- block_meta_ptr. row_count as usize ,
637
- & block_meta_ptr. compression ,
638
- & block_meta_ptr. col_metas ,
639
- column_chunks,
640
- & storage_format,
641
- )
642
- } )
663
+ let column_chunks = merged_io_read_result. columns_chunks ( ) ?;
664
+ reader. deserialize_chunks (
665
+ block_meta_ptr. location . 0 . as_str ( ) ,
666
+ block_meta_ptr. row_count as usize ,
667
+ & block_meta_ptr. compression ,
668
+ & block_meta_ptr. col_metas ,
669
+ column_chunks,
670
+ & storage_format,
671
+ )
672
+ } )
643
673
. await
644
674
. map_err ( |e| {
645
675
ErrorCode :: Internal (
646
676
"unexpected, failed to join aggregation context read block tasks for replace into." ,
647
677
)
648
- . add_message_back ( e. to_string ( ) )
678
+ . add_message_back ( e. to_string ( ) )
649
679
} ) ?
650
680
}
651
681
0 commit comments