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 |