be/src/storage/key/row_key_encoder.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 "storage/key/row_key_encoder.h" |
19 | | |
20 | | #include <cassert> |
21 | | |
22 | | #include "common/cast_set.h" |
23 | | #include "common/compiler_util.h" // IWYU pragma: keep |
24 | | #include "common/consts.h" |
25 | | #include "common/logging.h" |
26 | | #include "storage/iterator/olap_data_convertor.h" |
27 | | #include "storage/key_coder.h" |
28 | | #include "storage/tablet/tablet_schema.h" |
29 | | |
30 | | namespace doris { |
31 | | |
32 | | RowKeyEncoder::RowKeyEncoder(const TabletSchema& schema, bool mow) |
33 | 2.65k | : _num_short_key_columns(schema.num_short_key_columns()) { |
34 | 2.65k | if (mow) { |
35 | 141 | _init_mow(schema); |
36 | 2.51k | } else { |
37 | 2.51k | _init_non_mow(schema); |
38 | 2.51k | } |
39 | 2.65k | } |
40 | | |
41 | | RowKeyEncoder::RowKeyEncoder(const TabletSchema& schema) |
42 | 10 | : _num_short_key_columns(schema.num_short_key_columns()) { |
43 | 10 | _init_seq_coder(schema); |
44 | 10 | _add_default_sort_key_columns(schema); |
45 | 10 | } |
46 | | |
47 | 151 | void RowKeyEncoder::_init_seq_coder(const TabletSchema& schema) { |
48 | | // encode the sequence id into the primary key index |
49 | 151 | if (schema.has_sequence_col()) { |
50 | 61 | const auto& column = schema.column(schema.sequence_col_idx()); |
51 | 61 | _seq_coder = get_key_coder(column.type()); |
52 | 61 | _seq_col_length = column.length(); |
53 | 61 | } |
54 | 151 | } |
55 | | |
56 | 141 | void RowKeyEncoder::_init_mow(const TabletSchema& schema) { |
57 | 141 | _init_seq_coder(schema); |
58 | | |
59 | 141 | if (schema.cluster_key_uids().empty()) { |
60 | 133 | _add_default_sort_key_columns(schema); |
61 | 133 | return; |
62 | 133 | } |
63 | | |
64 | 49 | for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) { |
65 | 41 | _primary_key_coders.push_back(get_key_coder(schema.column(cid).type())); |
66 | 41 | } |
67 | 8 | _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT); |
68 | 47 | for (auto uid : schema.cluster_key_uids()) { |
69 | 47 | _add_sort_key_column(schema.column_by_uid(uid)); |
70 | 47 | } |
71 | 8 | } |
72 | | |
73 | 2.51k | void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) { |
74 | 2.51k | _add_default_sort_key_columns(schema); |
75 | 2.51k | } |
76 | | |
77 | 2.66k | void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) { |
78 | 5.06k | for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) { |
79 | 2.40k | _add_sort_key_column(schema.column(cid)); |
80 | 2.40k | } |
81 | 2.66k | } |
82 | | |
83 | 2.45k | void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) { |
84 | 2.45k | _sort_key_coders.push_back(get_key_coder(column.type())); |
85 | 2.45k | _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length())); |
86 | 2.45k | } |
87 | | |
88 | | std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns, |
89 | 7.45k | size_t pos) const { |
90 | 7.45k | assert(_sort_key_index_size.size() == _sort_key_coders.size()); |
91 | 7.45k | assert(key_columns.size() == _sort_key_coders.size()); |
92 | 7.45k | return _full_encode(_sort_key_coders, key_columns, pos); |
93 | 7.45k | } |
94 | | |
95 | | std::string RowKeyEncoder::full_encode_primary_keys( |
96 | 120 | const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const { |
97 | 120 | return _full_encode(_primary_key_coders, key_columns, pos); |
98 | 120 | } |
99 | | |
100 | | namespace { |
101 | | // Shared row-key encoding base: for each key column, write a null marker for |
102 | | // a null value, otherwise a normal marker followed by whatever `encode_field` |
103 | | // appends. `encode_field(cid, field, out)` is the only thing that differs between |
104 | | // the full key encode and the short-key prefix encode. |
105 | | template <typename EncodeField> |
106 | | std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos, |
107 | 21.1k | EncodeField&& encode_field) { |
108 | 21.1k | std::string encoded_keys; |
109 | 21.1k | size_t cid = 0; |
110 | 31.4k | for (const auto& column : key_columns) { |
111 | 31.4k | const auto* field = column->get_data_at(pos); |
112 | 31.4k | if (UNLIKELY(!field)) { |
113 | 292 | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); |
114 | 292 | ++cid; |
115 | 292 | continue; |
116 | 292 | } |
117 | 31.1k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); |
118 | 31.1k | encode_field(cid, field, &encoded_keys); |
119 | 31.1k | ++cid; |
120 | 31.1k | } |
121 | 21.1k | return encoded_keys; |
122 | 21.1k | } row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNS_13RowKeyEncoder12_full_encodeB5cxx11ERKSt6vectorIPKNS_8KeyCoderESaIS6_EERKS3_IPNS_23IOlapColumnDataAccessorESaISC_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESG_mOT_ Line | Count | Source | 107 | 7.57k | EncodeField&& encode_field) { | 108 | 7.57k | std::string encoded_keys; | 109 | 7.57k | size_t cid = 0; | 110 | 15.0k | for (const auto& column : key_columns) { | 111 | 15.0k | const auto* field = column->get_data_at(pos); | 112 | 15.0k | if (UNLIKELY(!field)) { | 113 | 170 | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); | 114 | 170 | ++cid; | 115 | 170 | continue; | 116 | 170 | } | 117 | 14.8k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); | 118 | 14.8k | encode_field(cid, field, &encoded_keys); | 119 | 14.8k | ++cid; | 120 | 14.8k | } | 121 | 7.57k | return encoded_keys; | 122 | 7.57k | } |
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_ Line | Count | Source | 107 | 13.5k | EncodeField&& encode_field) { | 108 | 13.5k | std::string encoded_keys; | 109 | 13.5k | size_t cid = 0; | 110 | 16.4k | for (const auto& column : key_columns) { | 111 | 16.4k | const auto* field = column->get_data_at(pos); | 112 | 16.4k | if (UNLIKELY(!field)) { | 113 | 122 | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); | 114 | 122 | ++cid; | 115 | 122 | continue; | 116 | 122 | } | 117 | 16.3k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); | 118 | 16.3k | encode_field(cid, field, &encoded_keys); | 119 | 16.3k | ++cid; | 120 | 16.3k | } | 121 | 13.5k | return encoded_keys; | 122 | 13.5k | } |
|
123 | | } // namespace |
124 | | |
125 | | std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders, |
126 | | const std::vector<IOlapColumnDataAccessor*>& key_columns, |
127 | 7.57k | size_t pos) { |
128 | 7.57k | assert(key_columns.size() == key_coders.size()); |
129 | 7.57k | return encode_key_columns(key_columns, pos, |
130 | 14.8k | [&](size_t cid, const void* field, std::string* out) { |
131 | 14.8k | DCHECK(key_coders[cid] != nullptr); |
132 | 14.8k | key_coders[cid]->full_encode_ascending(field, out); |
133 | 14.8k | }); |
134 | 7.57k | } |
135 | | |
136 | | std::string RowKeyEncoder::encode_short_keys( |
137 | 13.5k | const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const { |
138 | 13.5k | assert(key_columns.size() == _num_short_key_columns); |
139 | 13.5k | assert(key_columns.size() <= _sort_key_coders.size()); |
140 | 13.5k | return encode_key_columns( |
141 | 16.3k | key_columns, pos, [&](size_t cid, const void* field, std::string* out) { |
142 | 16.3k | _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out); |
143 | 16.3k | }); |
144 | 13.5k | } |
145 | | |
146 | | void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys, |
147 | 164 | const IOlapColumnDataAccessor* seq_column, size_t pos) const { |
148 | 164 | const auto* field = seq_column->get_data_at(pos); |
149 | | // So the primary key index can still use it, encode a null seq column as |
150 | | // the smallest value of its length. |
151 | 164 | if (UNLIKELY(!field)) { |
152 | 12 | encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER); |
153 | 12 | encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER); |
154 | 12 | return; |
155 | 12 | } |
156 | 152 | encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER); |
157 | 152 | _seq_coder->full_encode_ascending(field, encoded_keys); |
158 | 152 | } |
159 | | |
160 | 118 | void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const { |
161 | 118 | encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER); |
162 | 118 | _rowid_coder->full_encode_ascending(&rowid, encoded_keys); |
163 | 118 | } |
164 | | |
165 | | } // namespace doris |