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 | 3.62k | : _num_short_key_columns(schema.num_short_key_columns()) { |
34 | 3.62k | if (mow) { |
35 | 278 | _init_mow(schema); |
36 | 3.34k | } else { |
37 | 3.34k | _init_non_mow(schema); |
38 | 3.34k | } |
39 | 3.62k | } |
40 | | |
41 | 278 | void RowKeyEncoder::_init_mow(const TabletSchema& schema) { |
42 | | // encode the sequence id into the primary key index |
43 | 278 | if (schema.has_sequence_col()) { |
44 | 141 | const auto& column = schema.column(schema.sequence_col_idx()); |
45 | 141 | _seq_coder = get_key_coder(column.type()); |
46 | 141 | _seq_col_length = column.length(); |
47 | 141 | } |
48 | | |
49 | | // Which columns each view ends up holding: |
50 | | // |
51 | | // _sort_key_coders _primary_key_coders |
52 | | // no cluster key key columns key columns |
53 | | // cluster keys cluster key cols key columns |
54 | | // |
55 | | // The primary key index is built on the schema key columns whatever the segment sorts by, so |
56 | | // every mow table gets that view, not just the ones with cluster keys. The sort-key view |
57 | | // follows the segment's own order, which is the only column set that differs between the two. |
58 | 2.68k | for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) { |
59 | 2.40k | _primary_key_coders.push_back(get_key_coder(schema.column(cid).type())); |
60 | 2.40k | } |
61 | | |
62 | 278 | if (schema.cluster_key_uids().empty()) { |
63 | 254 | _add_default_sort_key_columns(schema); |
64 | 254 | return; |
65 | 254 | } |
66 | 24 | _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT); |
67 | 367 | for (auto uid : schema.cluster_key_uids()) { |
68 | 367 | _add_sort_key_column(schema.column_by_uid(uid)); |
69 | 367 | } |
70 | 24 | } |
71 | | |
72 | 3.34k | void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) { |
73 | 3.34k | _add_default_sort_key_columns(schema); |
74 | 3.34k | } |
75 | | |
76 | 3.60k | void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) { |
77 | 9.08k | for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) { |
78 | 5.48k | _add_sort_key_column(schema.column(cid)); |
79 | 5.48k | } |
80 | 3.60k | } |
81 | | |
82 | 5.85k | void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) { |
83 | 5.85k | _sort_key_coders.push_back(get_key_coder(column.type())); |
84 | 5.85k | _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length())); |
85 | 5.85k | } |
86 | | |
87 | | std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns, |
88 | 12.4k | size_t pos) const { |
89 | 12.4k | assert(_sort_key_index_size.size() == _sort_key_coders.size()); |
90 | 12.4k | assert(key_columns.size() == _sort_key_coders.size()); |
91 | 12.4k | return _full_encode(_sort_key_coders, key_columns, pos); |
92 | 12.4k | } |
93 | | |
94 | | std::string RowKeyEncoder::full_encode_primary_keys( |
95 | 1.43k | const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const { |
96 | 1.43k | return _full_encode(_primary_key_coders, key_columns, pos); |
97 | 1.43k | } |
98 | | |
99 | | namespace { |
100 | | // Shared row-key encoding base: for each key column, write a null marker for |
101 | | // a null value, otherwise a normal marker followed by whatever `encode_field` |
102 | | // appends. `encode_field(cid, field, out)` is the only thing that differs between |
103 | | // the full key encode and the short-key prefix encode. |
104 | | template <typename EncodeField> |
105 | | std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos, |
106 | 28.3k | EncodeField&& encode_field) { |
107 | 28.3k | std::string encoded_keys; |
108 | 28.3k | size_t cid = 0; |
109 | 48.8k | for (const auto& column : key_columns) { |
110 | 48.8k | const auto* field = column->get_data_at(pos); |
111 | 48.8k | if (UNLIKELY(!field)) { |
112 | 1.41k | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); |
113 | 1.41k | ++cid; |
114 | 1.41k | continue; |
115 | 1.41k | } |
116 | 47.4k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); |
117 | 47.4k | encode_field(cid, field, &encoded_keys); |
118 | 47.4k | ++cid; |
119 | 47.4k | } |
120 | 28.3k | return encoded_keys; |
121 | 28.3k | } 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 | 106 | 13.8k | EncodeField&& encode_field) { | 107 | 13.8k | std::string encoded_keys; | 108 | 13.8k | size_t cid = 0; | 109 | 30.6k | for (const auto& column : key_columns) { | 110 | 30.6k | const auto* field = column->get_data_at(pos); | 111 | 30.6k | if (UNLIKELY(!field)) { | 112 | 890 | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); | 113 | 890 | ++cid; | 114 | 890 | continue; | 115 | 890 | } | 116 | 29.7k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); | 117 | 29.7k | encode_field(cid, field, &encoded_keys); | 118 | 29.7k | ++cid; | 119 | 29.7k | } | 120 | 13.8k | return encoded_keys; | 121 | 13.8k | } |
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_ Line | Count | Source | 106 | 14.5k | EncodeField&& encode_field) { | 107 | 14.5k | std::string encoded_keys; | 108 | 14.5k | size_t cid = 0; | 109 | 18.1k | for (const auto& column : key_columns) { | 110 | 18.1k | const auto* field = column->get_data_at(pos); | 111 | 18.1k | if (UNLIKELY(!field)) { | 112 | 522 | encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER); | 113 | 522 | ++cid; | 114 | 522 | continue; | 115 | 522 | } | 116 | 17.6k | encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER); | 117 | 17.6k | encode_field(cid, field, &encoded_keys); | 118 | 17.6k | ++cid; | 119 | 17.6k | } | 120 | 14.5k | return encoded_keys; | 121 | 14.5k | } |
|
122 | | } // namespace |
123 | | |
124 | | std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders, |
125 | | const std::vector<IOlapColumnDataAccessor*>& key_columns, |
126 | 13.8k | size_t pos) { |
127 | 13.8k | assert(key_columns.size() == key_coders.size()); |
128 | 13.8k | return encode_key_columns(key_columns, pos, |
129 | 29.7k | [&](size_t cid, const void* field, std::string* out) { |
130 | 29.7k | DCHECK(key_coders[cid] != nullptr); |
131 | 29.7k | key_coders[cid]->full_encode_ascending(field, out); |
132 | 29.7k | }); |
133 | 13.8k | } |
134 | | |
135 | | std::string RowKeyEncoder::encode_short_keys( |
136 | 14.5k | const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const { |
137 | 14.5k | assert(key_columns.size() == _num_short_key_columns); |
138 | 14.5k | assert(key_columns.size() <= _sort_key_coders.size()); |
139 | 14.5k | return encode_key_columns( |
140 | 17.6k | key_columns, pos, [&](size_t cid, const void* field, std::string* out) { |
141 | 17.6k | _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out); |
142 | 17.6k | }); |
143 | 14.5k | } |
144 | | |
145 | | void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys, |
146 | 424 | const IOlapColumnDataAccessor* seq_column, size_t pos) const { |
147 | 424 | const auto* field = seq_column->get_data_at(pos); |
148 | | // So the primary key index can still use it, encode a null seq column as |
149 | | // the smallest value of its length. |
150 | 424 | if (UNLIKELY(!field)) { |
151 | 76 | encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER); |
152 | 76 | encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER); |
153 | 76 | return; |
154 | 76 | } |
155 | 348 | encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER); |
156 | 348 | _seq_coder->full_encode_ascending(field, encoded_keys); |
157 | 348 | } |
158 | | |
159 | 166 | void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const { |
160 | 166 | encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER); |
161 | 166 | _rowid_coder->full_encode_ascending(&rowid, encoded_keys); |
162 | 166 | } |
163 | | |
164 | | } // namespace doris |