Coverage Report

Created: 2026-10-27 20:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/load/memtable/memtable_aggregating.h
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
#pragma once
19
20
#include <memory>
21
#include <vector>
22
23
#include "core/arena.h"
24
#include "exprs/aggregate/aggregate_function.h"
25
#include "load/memtable/memtable.h"
26
27
namespace doris {
28
29
// Shared implementation of the models that merge rows with equal keys. AGG_KEYS and UNIQUE_KEYS
30
// both keep one RowInBlock per input row and aggregate the value columns into per-row states, so
31
// that mechanism lives here exactly once. The leaves only provide the model rules: which
32
// aggregate function a value column uses, and which extra columns partial update and sequence
33
// handling need.
34
class AggregatingMemTable : public MemTable {
35
public:
36
    ~AggregatingMemTable() override;
37
38
    void shrink_memtable_by_agg() override;
39
40
protected:
41
    AggregatingMemTable(int64_t tablet_id, std::shared_ptr<TabletSchema> tablet_schema,
42
                        const std::vector<SlotDescriptor*>* slot_descs, TupleDescriptor* tuple_desc,
43
                        PartialUpdateInfo* partial_update_info,
44
                        const std::shared_ptr<ResourceContext>& resource_ctx, bool need_lsn);
45
46
    // Share one tracked allocation across a batch. Allocating each row separately also retains an
47
    // address record and a stack trace per row when memory diagnostics are enabled.
48
    template <typename RowFactory>
49
83.8k
    static std::shared_ptr<RowInBlock[]> make_row_batch(size_t num_rows, RowFactory&& make_row) {
50
83.8k
        auto rows = std::allocate_shared<RowInBlock[]>(CustomStdAllocator<RowInBlock>(), num_rows);
51
8.66M
        for (size_t i = 0; i < num_rows; ++i) {
52
8.58M
            rows[i] = make_row(i);
53
8.58M
        }
54
83.8k
        return rows;
55
83.8k
    }
unity_2_cxx.cxx:_ZN5doris19AggregatingMemTable14make_row_batchIZNS_18UniqueKeysMemTable21_sort_by_cluster_keysEvE3$_0EESt10shared_ptrIA_NS_10RowInBlockEEmOT_
Line
Count
Source
49
1.53k
    static std::shared_ptr<RowInBlock[]> make_row_batch(size_t num_rows, RowFactory&& make_row) {
50
1.53k
        auto rows = std::allocate_shared<RowInBlock[]>(CustomStdAllocator<RowInBlock>(), num_rows);
51
823k
        for (size_t i = 0; i < num_rows; ++i) {
52
821k
            rows[i] = make_row(i);
53
821k
        }
54
1.53k
        return rows;
55
1.53k
    }
unity_1_cxx.cxx:_ZN5doris19AggregatingMemTable14make_row_batchIZNS0_20_append_row_metadataEmmRKSt6vectorIlNS_18CustomStdAllocatorIlNS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEEEEEE3$_0EESt10shared_ptrIA_NS_10RowInBlockEEmOT_
Line
Count
Source
49
82.2k
    static std::shared_ptr<RowInBlock[]> make_row_batch(size_t num_rows, RowFactory&& make_row) {
50
82.2k
        auto rows = std::allocate_shared<RowInBlock[]>(CustomStdAllocator<RowInBlock>(), num_rows);
51
7.83M
        for (size_t i = 0; i < num_rows; ++i) {
52
7.75M
            rows[i] = make_row(i);
53
7.75M
        }
54
82.2k
        return rows;
55
82.2k
    }
_ZN5doris19AggregatingMemTable14make_row_batchIZNS0_10_aggregateILb0ELb0EEEvvEUlmE_EESt10shared_ptrIA_NS_10RowInBlockEEmOT_
Line
Count
Source
49
10
    static std::shared_ptr<RowInBlock[]> make_row_batch(size_t num_rows, RowFactory&& make_row) {
50
10
        auto rows = std::allocate_shared<RowInBlock[]>(CustomStdAllocator<RowInBlock>(), num_rows);
51
8.20k
        for (size_t i = 0; i < num_rows; ++i) {
52
8.19k
            rows[i] = make_row(i);
53
8.19k
        }
54
10
        return rows;
55
10
    }
Unexecuted instantiation: _ZN5doris19AggregatingMemTable14make_row_batchIZNS0_10_aggregateILb0ELb1EEEvvEUlmE_EESt10shared_ptrIA_NS_10RowInBlockEEmOT_
56
57
    Status _on_first_insertion() override;
58
    void _reserve_rows(size_t num_rows, size_t cursor) override;
59
    void _append_row_metadata(size_t num_rows, size_t cursor,
60
                              const DorisVector<int64_t>& allocated_lsns) override;
61
    size_t _sort() override;
62
    Status _put_into_output(Block& in_block) override;
63
    Status _to_block(std::unique_ptr<Block>* res) override;
64
65
    // Resolve the per-block column positions aggregation needs. Called before _init_agg_functions
66
    // because the aggregate function of a column depends on them.
67
    virtual void _init_aggregation_columns();
68
    // Aggregate function used for one value column.
69
    virtual AggregateFunctionPtr _make_agg_function(int cid);
70
    // Flexible partial update is only reachable for UNIQUE_KEYS, which owns the delete sign and
71
    // skip bitmap rules. Pure virtual so a model that sets _skip_bitmap_col_idx without providing
72
    // the rules fails to compile instead of aborting the BE at run time.
73
    virtual void _aggregate_flexible_partial_update(
74
            bool is_final, MutableBlock& mutable_block,
75
            DorisVector<std::shared_ptr<RowInBlock>>& temp_row_in_blocks) = 0;
76
    // Ordering applied after aggregation; UNIQUE merge-on-write sorts by cluster keys.
77
4.97k
    virtual Status _after_aggregate() { return Status::OK(); }
78
79
    // Merge allocated LSN sidecar only when MemTable merges two RowInBlock objects.
80
    // Table models that require complex merge semantics, such as AGG tables and unique key
81
    // merge-on-read tables, do not support allocated LSN now; MemTableWriter::init() rejects such
82
    // a configuration before the first row is inserted.
83
    void _merge_allocated_lsn(RowInBlock* src_row, RowInBlock* dst_row);
84
85
    void _append_output_allocated_lsn(RowInBlock* row);
86
87
    template <bool has_skip_bitmap_col>
88
    void _aggregate_two_row_in_block(MutableBlock& mutable_block, RowInBlock* src_row,
89
                                     RowInBlock* dst_row);
90
91
    void _aggregate_two_row_with_sequence_map(MutableBlock& mutable_block, RowInBlock* src_row,
92
                                              RowInBlock* dst_row);
93
94
    template <bool is_final>
95
    void _finalize_one_row(RowInBlock* row, MutableBlock& mutable_block, int row_pos);
96
    void _init_row_for_agg(RowInBlock* row, MutableBlock& mutable_block);
97
    void _clear_row_agg(RowInBlock* row);
98
99
    template <bool is_final, bool has_skip_bitmap_col = false>
100
    void _aggregate();
101
102
    void _init_agg_functions();
103
104
    // Holds only the tablet schema, so it is a value member: no heap allocation and no shared
105
    // ownership to reason about.
106
    RowInBlockComparator _vec_row_comparator;
107
108
    // Only the rows will be inserted into block can allocate memory from _arena.
109
    // In this way, we can make MemTable::memory_usage() to be more accurate, and eventually
110
    // reduce the number of segment files that are generated by current load
111
    Arena _arena;
112
113
    // One RowInBlock per input row. Those models still need per-row aggregation state and, when
114
    // enabled, the allocated LSN stored in RowInBlock.
115
    std::unique_ptr<DorisVector<std::shared_ptr<RowInBlock>>> _row_in_blocks;
116
117
    std::vector<AggregateFunctionPtr> _agg_functions;
118
    std::vector<size_t> _offsets_of_aggregate_states;
119
    size_t _total_size_of_aggregate_states = 0;
120
    size_t _last_agg_pos = 0;
121
122
    int32_t _seq_col_idx_in_block {-1};
123
    int32_t _skip_bitmap_col_idx {-1};
124
};
125
126
// Defined in memtable_aggregating.cpp. The skip-bitmap variant is only reached from the UNIQUE_KEYS
127
// flexible partial update path, which lives in another translation unit.
128
extern template void AggregatingMemTable::_aggregate_two_row_in_block<true>(
129
        MutableBlock& mutable_block, RowInBlock* src_row, RowInBlock* dst_row);
130
131
} // namespace doris