Coverage Report

Created: 2026-08-06 11:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/olap_common.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 <gen_cpp/Types_types.h>
21
#include <netinet/in.h>
22
23
#include <atomic>
24
#include <charconv>
25
#include <cstdint>
26
#include <functional>
27
#include <list>
28
#include <map>
29
#include <memory>
30
#include <ostream>
31
#include <sstream>
32
#include <string>
33
#include <typeinfo>
34
#include <unordered_map>
35
#include <unordered_set>
36
#include <utility>
37
38
#include "common/cast_set.h"
39
#include "common/config.h"
40
#include "common/exception.h"
41
#include "io/io_common.h"
42
#include "storage/index/inverted/inverted_index_stats.h"
43
#include "storage/olap_define.h"
44
#include "storage/rowset/rowset_fwd.h"
45
#include "util/hash_util.hpp"
46
#include "util/time.h"
47
#include "util/uid_util.h"
48
49
namespace doris {
50
static constexpr int64_t MAX_ROWSET_ID = 1L << 56;
51
static constexpr int64_t LOW_56_BITS = 0x00ffffffffffffff;
52
53
using SchemaHash = int32_t;
54
using int128_t = __int128;
55
using uint128_t = unsigned __int128;
56
57
using TabletUid = UniqueId;
58
59
enum CompactionType {
60
    BASE_COMPACTION = 1,
61
    CUMULATIVE_COMPACTION = 2,
62
    FULL_COMPACTION = 3,
63
    BINLOG_COMPACTION = 4
64
};
65
66
struct CompactionScoreStats {
67
    int64_t max_score = 0;
68
    int64_t size_based_max_score = 0;
69
    int64_t time_series_max_score = 0;
70
    bool scanned = false;
71
};
72
73
enum DataDirType {
74
    SPILL_DISK_DIR,
75
    OLAP_DATA_DIR,
76
    DATA_CACHE_DIR,
77
};
78
79
struct DataDirInfo {
80
    std::string path;
81
    size_t path_hash = 0;
82
    int64_t disk_capacity = 1; // actual disk capacity
83
    int64_t available = 0;     // available space, in bytes unit
84
    int64_t local_used_capacity = 0;
85
    int64_t remote_used_capacity = 0;
86
    int64_t trash_used_capacity = 0;
87
    bool is_used = false;                                      // whether available mark
88
    TStorageMedium::type storage_medium = TStorageMedium::HDD; // Storage medium type: SSD|HDD
89
    DataDirType data_dir_type = DataDirType::OLAP_DATA_DIR;
90
    std::string metric_name;
91
};
92
93
// Sort DataDirInfo by available space.
94
struct DataDirInfoLessAvailability {
95
21
    bool operator()(const DataDirInfo& left, const DataDirInfo& right) const {
96
21
        return left.available < right.available;
97
21
    }
98
};
99
100
struct TabletInfo {
101
    TabletInfo(TTabletId in_tablet_id, UniqueId in_uid)
102
2.29M
            : tablet_id(in_tablet_id), tablet_uid(in_uid) {}
103
104
12.6M
    bool operator<(const TabletInfo& right) const {
105
12.6M
        if (tablet_id != right.tablet_id) {
106
12.0M
            return tablet_id < right.tablet_id;
107
12.0M
        } else {
108
573k
            return tablet_uid < right.tablet_uid;
109
573k
        }
110
12.6M
    }
111
112
88
    std::string to_string() const {
113
88
        std::stringstream ss;
114
88
        ss << tablet_id << "." << tablet_uid.to_string();
115
88
        return ss.str();
116
88
    }
117
118
    TTabletId tablet_id;
119
    UniqueId tablet_uid;
120
};
121
122
struct TabletSize {
123
    TabletSize(TTabletId in_tablet_id, size_t in_tablet_size)
124
0
            : tablet_id(in_tablet_id), tablet_size(in_tablet_size) {}
125
126
    TTabletId tablet_id;
127
    size_t tablet_size;
128
};
129
130
// Storage-engine cell types, used by TabletColumn / KeyCoder and the
131
// data_type traits chain. When adding a new value, also extend CppTypeTraits,
132
// FieldTypeTraits and the field_type_size() switch in storage/types.h. Decide how it maps to
133
// PrimitiveType and explicitly define its behavior in primitive_type_to_storage_field_type() and
134
// storage_field_type_to_primitive_type(), either by providing a mapping or by throwing.
135
enum class FieldType {
136
    OLAP_FIELD_TYPE_TINYINT = 1, // MYSQL_TYPE_TINY
137
    OLAP_FIELD_TYPE_UNSIGNED_TINYINT = 2,
138
    OLAP_FIELD_TYPE_SMALLINT = 3, // MYSQL_TYPE_SHORT
139
    OLAP_FIELD_TYPE_UNSIGNED_SMALLINT = 4,
140
    OLAP_FIELD_TYPE_INT = 5, // MYSQL_TYPE_LONG
141
    OLAP_FIELD_TYPE_UNSIGNED_INT = 6,
142
    OLAP_FIELD_TYPE_BIGINT = 7, // MYSQL_TYPE_LONGLONG
143
    OLAP_FIELD_TYPE_UNSIGNED_BIGINT = 8,
144
    OLAP_FIELD_TYPE_LARGEINT = 9,
145
    OLAP_FIELD_TYPE_FLOAT = 10,  // MYSQL_TYPE_FLOAT
146
    OLAP_FIELD_TYPE_DOUBLE = 11, // MYSQL_TYPE_DOUBLE
147
    OLAP_FIELD_TYPE_DISCRETE_DOUBLE = 12,
148
    OLAP_FIELD_TYPE_CHAR = 13,     // MYSQL_TYPE_STRING
149
    OLAP_FIELD_TYPE_DATE = 14,     // MySQL_TYPE_NEWDATE
150
    OLAP_FIELD_TYPE_DATETIME = 15, // MySQL_TYPE_DATETIME
151
    OLAP_FIELD_TYPE_DECIMAL = 16,  // DECIMAL, using different store format against MySQL
152
    OLAP_FIELD_TYPE_VARCHAR = 17,
153
154
    OLAP_FIELD_TYPE_STRUCT = 18,  // Struct
155
    OLAP_FIELD_TYPE_ARRAY = 19,   // ARRAY
156
    OLAP_FIELD_TYPE_MAP = 20,     // Map
157
    OLAP_FIELD_TYPE_UNKNOWN = 21, // UNKNOW OLAP_FIELD_TYPE_STRING
158
    OLAP_FIELD_TYPE_NONE = 22,
159
    OLAP_FIELD_TYPE_HLL = 23,
160
    OLAP_FIELD_TYPE_BOOL = 24,
161
    OLAP_FIELD_TYPE_BITMAP = 25,
162
    OLAP_FIELD_TYPE_STRING = 26,
163
    OLAP_FIELD_TYPE_QUANTILE_STATE = 27,
164
    OLAP_FIELD_TYPE_DATEV2 = 28,
165
    OLAP_FIELD_TYPE_DATETIMEV2 = 29,
166
    OLAP_FIELD_TYPE_TIMEV2 = 30,
167
    OLAP_FIELD_TYPE_DECIMAL32 = 31,
168
    OLAP_FIELD_TYPE_DECIMAL64 = 32,
169
    OLAP_FIELD_TYPE_DECIMAL128I = 33,
170
    OLAP_FIELD_TYPE_JSONB = 34,
171
    OLAP_FIELD_TYPE_VARIANT = 35,
172
    OLAP_FIELD_TYPE_AGG_STATE = 36,
173
    OLAP_FIELD_TYPE_DECIMAL256 = 37,
174
    OLAP_FIELD_TYPE_IPV4 = 38,
175
    OLAP_FIELD_TYPE_IPV6 = 39,
176
    OLAP_FIELD_TYPE_TIMESTAMPTZ = 40,
177
};
178
179
// Define all aggregation methods supported by TabletColumn
180
// Note that in practice, not all types can use all the following aggregation methods
181
// For example, it is meaningless to use SUM for the string type (but it will not cause the program to crash)
182
// The implementation of the TabletColumn class does not perform such checks, and should be constrained when creating the table
183
enum class FieldAggregationMethod {
184
    OLAP_FIELD_AGGREGATION_NONE = 0,
185
    OLAP_FIELD_AGGREGATION_SUM = 1,
186
    OLAP_FIELD_AGGREGATION_MIN = 2,
187
    OLAP_FIELD_AGGREGATION_MAX = 3,
188
    OLAP_FIELD_AGGREGATION_REPLACE = 4,
189
    OLAP_FIELD_AGGREGATION_HLL_UNION = 5,
190
    OLAP_FIELD_AGGREGATION_UNKNOWN = 6,
191
    OLAP_FIELD_AGGREGATION_BITMAP_UNION = 7,
192
    // Replace if and only if added value is not null
193
    OLAP_FIELD_AGGREGATION_REPLACE_IF_NOT_NULL = 8,
194
    OLAP_FIELD_AGGREGATION_QUANTILE_UNION = 9,
195
    OLAP_FIELD_AGGREGATION_GENERIC = 10
196
};
197
198
enum class PushType {
199
    PUSH_NORMAL = 1,          // for broker/hadoop load, not used any more
200
    PUSH_FOR_DELETE = 2,      // for delete
201
    PUSH_FOR_LOAD_DELETE = 3, // not used any more
202
    PUSH_NORMAL_V2 = 4,       // for spark load
203
};
204
205
12.6M
constexpr bool field_is_slice_type(const FieldType& field_type) {
206
12.6M
    return field_type == FieldType::OLAP_FIELD_TYPE_VARCHAR ||
207
12.6M
           field_type == FieldType::OLAP_FIELD_TYPE_CHAR ||
208
12.6M
           field_type == FieldType::OLAP_FIELD_TYPE_STRING;
209
12.6M
}
210
211
439k
constexpr bool field_is_decimal_type(const FieldType& field_type) {
212
439k
    return field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL ||
213
439k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL32 ||
214
439k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL64 ||
215
439k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL128I ||
216
439k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL256;
217
439k
}
218
219
39.0k
constexpr bool field_is_numeric_type(const FieldType& field_type) {
220
39.0k
    return field_type == FieldType::OLAP_FIELD_TYPE_INT ||
221
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT ||
222
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_BIGINT ||
223
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_SMALLINT ||
224
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_TINYINT ||
225
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_UNSIGNED_SMALLINT ||
226
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_TINYINT ||
227
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DOUBLE ||
228
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_FLOAT ||
229
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DATE ||
230
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DATEV2 ||
231
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DATETIME ||
232
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DATETIMEV2 ||
233
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ ||
234
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_LARGEINT ||
235
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL ||
236
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL32 ||
237
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL64 ||
238
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL128I ||
239
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_DECIMAL256 ||
240
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_BOOL ||
241
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_IPV4 ||
242
39.0k
           field_type == FieldType::OLAP_FIELD_TYPE_IPV6;
243
39.0k
}
244
245
// <start_version_id, end_version_id>, such as <100, 110>
246
//using Version = std::pair<TupleVersion, TupleVersion>;
247
248
struct Version {
249
    int64_t first;
250
    int64_t second;
251
252
102M
    Version(int64_t first_, int64_t second_) : first(first_), second(second_) {}
253
17.4M
    Version() : first(0), second(0) {}
254
255
8.85k
    static Version mock() {
256
        // Every time SchemaChange is used for external rowing, some temporary versions (such as 999, 1000, 1001) will be written, in order to avoid Cache conflicts, temporary
257
        // The version number takes a BIG NUMBER plus the version number of the current SchemaChange
258
8.85k
        return Version(1 << 28, 1 << 29);
259
8.85k
    }
260
261
    friend std::ostream& operator<<(std::ostream& os, const Version& version);
262
263
9.82k
    bool operator!=(const Version& rhs) const { return first != rhs.first || second != rhs.second; }
264
265
10.5M
    bool operator==(const Version& rhs) const { return first == rhs.first && second == rhs.second; }
266
267
3.62M
    bool contains(const Version& other) const {
268
3.62M
        return first <= other.first && second >= other.second;
269
3.62M
    }
270
271
408k
    std::string to_string() const { return fmt::format("[{}-{}]", first, second); }
272
};
273
274
struct TsoRange : public Version {
275
14.0M
    TsoRange() : Version(-1, -1) {}
276
4.38M
    TsoRange(int64_t start_tso, int64_t end_tso) : Version(start_tso, end_tso) {}
277
278
157k
    int64_t start_tso() const { return first; }
279
11.1M
    int64_t end_tso() const { return second; }
280
281
0
    bool contains(const TsoRange& other) const { return Version::contains(other); }
282
};
283
284
using Versions = std::vector<Version>;
285
286
16.4k
inline std::ostream& operator<<(std::ostream& os, const Version& version) {
287
16.4k
    return os << version.to_string();
288
16.4k
}
289
290
0
inline std::ostream& operator<<(std::ostream& os, const Versions& versions) {
291
0
    for (auto& version : versions) {
292
0
        os << version;
293
0
    }
294
0
    return os;
295
0
}
296
297
// used for hash-struct of hash_map<Version, Rowset*>.
298
struct HashOfVersion {
299
11.8M
    size_t operator()(const Version& version) const {
300
11.8M
        size_t seed = 0;
301
11.8M
        seed = HashUtil::hash64(&version.first, sizeof(version.first), seed);
302
11.8M
        seed = HashUtil::hash64(&version.second, sizeof(version.second), seed);
303
11.8M
        return seed;
304
11.8M
    }
305
};
306
307
// It is used to represent Graph vertex.
308
struct Vertex {
309
    int64_t value = 0;
310
    std::list<int64_t> edges;
311
312
1.33M
    Vertex(int64_t v) : value(v) {}
313
};
314
315
// ReaderStatistics used to collect statistics when scan data from storage
316
struct OlapReaderStatistics {
317
    int64_t io_ns = 0;
318
    int64_t compressed_bytes_read = 0;
319
320
    int64_t decompress_ns = 0;
321
    int64_t uncompressed_bytes_read = 0;
322
323
    // total read bytes in memory
324
    int64_t bytes_read = 0;
325
326
    int64_t block_fetch_ns = 0; // time of rowset reader's `next_batch()` call
327
    int64_t block_load_ns = 0;
328
    int64_t blocks_load = 0;
329
    // Not used any more, will be removed after non-vectorized code is removed
330
    int64_t block_seek_num = 0;
331
    // Not used any more, will be removed after non-vectorized code is removed
332
    int64_t block_seek_ns = 0;
333
334
    // block_load_ns
335
    //      block_init_ns
336
    //          block_init_seek_ns
337
    //          generate_row_ranges_ns
338
    //      predicate_column_read_ns
339
    //          predicate_column_read_seek_ns
340
    //      lazy_read_ns
341
    //          block_lazy_read_seek_ns
342
    int64_t block_init_ns = 0;
343
    int64_t block_init_seek_num = 0;
344
    int64_t block_init_seek_ns = 0;
345
    int64_t predicate_column_read_ns = 0;
346
    int64_t non_predicate_read_ns = 0;
347
    int64_t predicate_column_read_seek_num = 0;
348
    int64_t predicate_column_read_seek_ns = 0;
349
    int64_t lazy_read_ns = 0;
350
    int64_t block_lazy_read_seek_num = 0;
351
    int64_t block_lazy_read_seek_ns = 0;
352
    int64_t lazy_read_pruned_ns = 0;
353
354
    int64_t raw_rows_read = 0;
355
356
    int64_t rows_vec_cond_filtered = 0;
357
    int64_t rows_short_circuit_cond_filtered = 0;
358
    int64_t rows_expr_cond_filtered = 0;
359
    int64_t vec_cond_input_rows = 0;
360
    int64_t short_circuit_cond_input_rows = 0;
361
    int64_t expr_cond_input_rows = 0;
362
    int64_t rows_vec_del_cond_filtered = 0;
363
    int64_t vec_cond_ns = 0;
364
    int64_t short_cond_ns = 0;
365
    int64_t expr_filter_ns = 0;
366
    int64_t output_col_ns = 0;
367
    int64_t rows_key_range_filtered = 0;
368
    int64_t rows_stats_filtered = 0;
369
    int64_t rows_stats_rp_filtered = 0;
370
    int64_t expr_zonemap_filtered_segments = 0;
371
    int64_t expr_zonemap_filtered_pages = 0;
372
    int64_t expr_zonemap_unusable_evals = 0;
373
    int64_t in_zonemap_point_check_count = 0;
374
    int64_t in_zonemap_range_only_count = 0;
375
    int64_t rows_bf_filtered = 0;
376
    int64_t segment_dict_filtered = 0;
377
    // Including the number of rows filtered out according to the Delete information in the Tablet,
378
    // and the number of rows filtered for marked deleted rows under the unique key model.
379
    // This metric is mainly used to record the number of rows filtered by the delete condition in Segment V1,
380
    // and it is also used to record the replaced rows in the Unique key model in the "Reader" class.
381
    // In segmentv2, if you want to get all filtered rows, you need the sum of "rows_del_filtered" and "rows_conditions_filtered".
382
    int64_t rows_del_filtered = 0;
383
    int64_t rows_del_by_bitmap = 0;
384
    // the number of rows filtered by various column indexes.
385
    int64_t rows_conditions_filtered = 0;
386
    int64_t generate_row_ranges_by_keys_ns = 0;
387
    int64_t generate_row_ranges_by_column_conditions_ns = 0;
388
    int64_t generate_row_ranges_by_bf_ns = 0;
389
    int64_t generate_row_ranges_by_zonemap_ns = 0;
390
    int64_t generate_row_ranges_by_dict_ns = 0;
391
392
    int64_t index_load_ns = 0;
393
394
    int64_t total_pages_num = 0;
395
    int64_t cached_pages_num = 0;
396
397
    int64_t rows_inverted_index_filtered = 0;
398
    int64_t inverted_index_filter_timer = 0;
399
    int64_t inverted_index_query_timer = 0;
400
    int64_t inverted_index_query_cache_hit = 0;
401
    int64_t inverted_index_query_cache_miss = 0;
402
    int64_t inverted_index_query_null_bitmap_timer = 0;
403
    int64_t inverted_index_query_bitmap_copy_timer = 0;
404
    int64_t inverted_index_searcher_open_timer = 0;
405
    int64_t inverted_index_searcher_search_timer = 0;
406
    int64_t inverted_index_searcher_search_init_timer = 0;
407
    int64_t inverted_index_searcher_search_exec_timer = 0;
408
    int64_t inverted_index_searcher_cache_hit = 0;
409
    int64_t inverted_index_searcher_cache_miss = 0;
410
    int64_t inverted_index_downgrade_count = 0;
411
    int64_t inverted_index_analyzer_timer = 0;
412
    int64_t inverted_index_lookup_timer = 0;
413
    InvertedIndexStatistics inverted_index_stats;
414
415
    int64_t ann_index_load_ns = 0;
416
    int64_t ann_topn_search_ns = 0;
417
    int64_t ann_index_topn_search_cnt = 0;
418
    int64_t ann_ivf_on_disk_load_ns = 0;
419
    int64_t ann_ivf_on_disk_cache_hit_cnt = 0;
420
    int64_t ann_ivf_on_disk_cache_miss_cnt = 0;
421
    int64_t ann_index_cache_hits = 0;
422
423
    // Detailed timing for ANN operations
424
    int64_t ann_index_topn_engine_search_ns = 0;  // time spent in engine for range search
425
    int64_t ann_index_topn_result_process_ns = 0; // time spent processing TopN results
426
    int64_t ann_index_topn_engine_convert_ns = 0; // time spent on FAISS-side conversions (TopN)
427
    int64_t ann_index_topn_engine_prepare_ns =
428
            0; // time spent preparing before engine search (TopN)
429
    int64_t rows_ann_index_topn_filtered = 0;
430
431
    int64_t ann_index_range_search_ns = 0;
432
    int64_t ann_index_range_search_cnt = 0;
433
    // Detailed timing for ANN Range search
434
    int64_t ann_range_engine_search_ns = 0; // time spent in engine for range search
435
    int64_t ann_range_pre_process_ns = 0;   // time spent preparing before engine search
436
437
    int64_t ann_range_result_convert_ns = 0; // time spent processing range results
438
    int64_t ann_range_engine_convert_ns = 0; // time spent on FAISS-side conversions (Range)
439
    int64_t rows_ann_index_range_filtered = 0;
440
    int64_t ann_index_range_cache_hits = 0;
441
    int64_t ann_fall_back_brute_force_cnt = 0;
442
    int64_t ann_topn_fallback_by_small_candidate_cnt = 0;
443
    int64_t ann_topn_fallback_small_candidate_rows = 0;
444
    int64_t ann_range_fallback_by_small_candidate_cnt = 0;
445
    int64_t ann_range_fallback_small_candidate_rows = 0;
446
447
    int64_t output_index_result_column_timer = 0;
448
    // number of segment filtered by column stat when creating seg iterator
449
    int64_t filtered_segment_number = 0;
450
    // number of segment with condition cache hit
451
    int64_t condition_cache_hit_seg_nums = 0;
452
    // number of rows filtered by condition cache hit
453
    int64_t condition_cache_filtered_rows = 0;
454
    // total number of segment
455
    int64_t total_segment_number = 0;
456
457
    io::FileCacheStatistics file_cache_stats;
458
    int64_t load_segments_timer = 0;
459
460
    int64_t collect_iterator_merge_next_timer = 0;
461
    int64_t collect_iterator_normal_next_timer = 0;
462
    int64_t delete_bitmap_get_agg_ns = 0;
463
464
    int64_t tablet_reader_init_timer_ns = 0;
465
    int64_t tablet_reader_capture_rs_readers_timer_ns = 0;
466
    int64_t tablet_reader_init_return_columns_timer_ns = 0;
467
    int64_t tablet_reader_init_keys_param_timer_ns = 0;
468
    int64_t tablet_reader_init_orderby_keys_param_timer_ns = 0;
469
    int64_t tablet_reader_init_conditions_param_timer_ns = 0;
470
    int64_t tablet_reader_init_delete_condition_param_timer_ns = 0;
471
    int64_t block_reader_vcollect_iter_init_timer_ns = 0;
472
    int64_t block_reader_rs_readers_init_timer_ns = 0;
473
    int64_t block_reader_build_heap_init_timer_ns = 0;
474
475
    int64_t rowset_reader_get_segment_iterators_timer_ns = 0;
476
    int64_t rowset_reader_create_iterators_timer_ns = 0;
477
    int64_t rowset_reader_init_iterators_timer_ns = 0;
478
    int64_t rowset_reader_load_segments_timer_ns = 0;
479
480
    int64_t segment_iterator_init_timer_ns = 0;
481
    int64_t segment_iterator_init_return_column_iterators_timer_ns = 0;
482
    int64_t segment_iterator_init_index_iterators_timer_ns = 0;
483
    int64_t segment_iterator_init_segment_prefetchers_timer_ns = 0;
484
485
    int64_t segment_create_column_readers_timer_ns = 0;
486
    int64_t segment_load_index_timer_ns = 0;
487
488
    int64_t adaptive_batch_size_predict_min_rows = INT64_MAX;
489
    int64_t adaptive_batch_size_predict_max_rows = 0;
490
491
    int64_t variant_scan_sparse_column_timer_ns = 0;
492
    int64_t variant_scan_sparse_column_bytes = 0;
493
    int64_t variant_fill_path_from_sparse_column_timer_ns = 0;
494
    int64_t variant_subtree_default_iter_count = 0;
495
    int64_t variant_subtree_leaf_iter_count = 0;
496
    int64_t variant_subtree_hierarchical_iter_count = 0;
497
    int64_t variant_subtree_sparse_iter_count = 0;
498
    int64_t variant_doc_value_column_iter_count = 0;
499
};
500
501
using ColumnId = uint32_t;
502
// Column unique id set
503
using UniqueIdSet = std::set<uint32_t>;
504
// Column unique Id -> column id map
505
using UniqueIdToColumnIdMap = std::map<ColumnId, ColumnId>;
506
507
// 8 bit rowset id version
508
// 56 bit, inc number from 1
509
// 128 bit backend uid, it is a uuid bit, id version
510
struct RowsetId {
511
    int8_t version = 0;
512
    int64_t hi = 0;
513
    int64_t mi = 0;
514
    int64_t lo = 0;
515
516
999k
    void init(std::string_view rowset_id_str) {
517
        // for new rowsetid its a 48 hex string
518
        // if the len < 48, then it is an old format rowset id
519
999k
        if (rowset_id_str.length() < 48) [[unlikely]] {
520
149
            int64_t high;
521
149
            auto [_, ec] = std::from_chars(rowset_id_str.data(),
522
149
                                           rowset_id_str.data() + rowset_id_str.length(), high);
523
149
            if (ec != std::errc {}) [[unlikely]] {
524
1
                if (config::force_regenerate_rowsetid_on_start_error) {
525
1
                    LOG(WARNING) << "failed to init rowset id: " << rowset_id_str;
526
1
                    high = MAX_ROWSET_ID - 1;
527
1
                } else {
528
0
                    throw Exception(
529
0
                            Status::FatalError("failed to init rowset id: {}", rowset_id_str));
530
0
                }
531
1
            }
532
149
            init(1, high, 0, 0);
533
999k
        } else {
534
999k
            int64_t high = 0;
535
999k
            int64_t middle = 0;
536
999k
            int64_t low = 0;
537
999k
            from_hex(&high, rowset_id_str.substr(0, 16));
538
999k
            from_hex(&middle, rowset_id_str.substr(16, 16));
539
999k
            from_hex(&low, rowset_id_str.substr(32, 16));
540
999k
            init(high >> 56, high & LOW_56_BITS, middle, low);
541
999k
        }
542
999k
    }
543
544
    // to compatible with old version
545
4.72k
    void init(int64_t rowset_id) { init(1, rowset_id, 0, 0); }
546
547
1.40M
    void init(int64_t id_version, int64_t high, int64_t middle, int64_t low) {
548
1.40M
        version = cast_set<int8_t>(id_version);
549
1.40M
        if (UNLIKELY(high >= MAX_ROWSET_ID)) {
550
0
            throw Exception(Status::FatalError("inc rowsetid is too large:{}", high));
551
0
        }
552
1.40M
        hi = (id_version << 56) + (high & LOW_56_BITS);
553
1.40M
        mi = middle;
554
1.40M
        lo = low;
555
1.40M
    }
556
557
8.80M
    std::string to_string() const {
558
8.80M
        if (version < 2) {
559
23.3k
            return std::to_string(hi & LOW_56_BITS);
560
8.78M
        } else {
561
8.78M
            char buf[48];
562
8.78M
            to_hex(hi, buf);
563
8.78M
            to_hex(mi, buf + 16);
564
8.78M
            to_hex(lo, buf + 32);
565
8.78M
            return {buf, 48};
566
8.78M
        }
567
8.80M
    }
568
569
    // std::unordered_map need this api
570
8.44M
    bool operator==(const RowsetId& rhs) const {
571
8.44M
        return hi == rhs.hi && mi == rhs.mi && lo == rhs.lo;
572
8.44M
    }
573
574
1.81M
    bool operator!=(const RowsetId& rhs) const {
575
1.81M
        return hi != rhs.hi || mi != rhs.mi || lo != rhs.lo;
576
1.81M
    }
577
578
174M
    bool operator<(const RowsetId& rhs) const {
579
174M
        if (hi != rhs.hi) {
580
74.3M
            return hi < rhs.hi;
581
100M
        } else if (mi != rhs.mi) {
582
6.49M
            return mi < rhs.mi;
583
93.9M
        } else {
584
93.9M
            return lo < rhs.lo;
585
93.9M
        }
586
174M
    }
587
588
90.1k
    friend std::ostream& operator<<(std::ostream& out, const RowsetId& rowset_id) {
589
90.1k
        out << rowset_id.to_string();
590
90.1k
        return out;
591
90.1k
    }
592
};
593
594
using RowsetIdUnorderedSet = std::unordered_set<RowsetId>;
595
596
// Extract rowset id from filename, return uninitialized rowset id if filename is invalid
597
90.2k
inline RowsetId extract_rowset_id(std::string_view filename) {
598
90.2k
    RowsetId rowset_id;
599
90.2k
    if (filename.ends_with(".dat")) {
600
        // filename format: {rowset_id}_{segment_num}.dat
601
81.1k
        auto end = filename.find('_');
602
81.1k
        if (end == std::string::npos) {
603
0
            return rowset_id;
604
0
        }
605
81.1k
        rowset_id.init(filename.substr(0, end));
606
81.1k
        return rowset_id;
607
81.1k
    }
608
9.08k
    if (filename.ends_with(".idx")) {
609
        // filename format: {rowset_id}_{segment_num}_{index_id}.idx
610
8.86k
        auto end = filename.find('_');
611
8.86k
        if (end == std::string::npos) {
612
0
            return rowset_id;
613
0
        }
614
8.86k
        rowset_id.init(filename.substr(0, end));
615
8.86k
        return rowset_id;
616
8.86k
    }
617
216
    return rowset_id;
618
9.08k
}
619
620
class DeleteBitmap;
621
// merge on write context
622
struct MowContext {
623
    MowContext(int64_t version, int64_t txnid, std::shared_ptr<RowsetIdUnorderedSet> ids,
624
               std::vector<RowsetSharedPtr> rowset_ptrs, std::shared_ptr<DeleteBitmap> db)
625
85.9k
            : max_version(version),
626
85.9k
              txn_id(txnid),
627
85.9k
              rowset_ids(std::move(ids)),
628
85.9k
              rowset_ptrs(std::move(rowset_ptrs)),
629
85.9k
              delete_bitmap(std::move(db)) {}
630
    int64_t max_version;
631
    int64_t txn_id;
632
    std::shared_ptr<RowsetIdUnorderedSet> rowset_ids;
633
    std::vector<RowsetSharedPtr> rowset_ptrs;
634
    std::shared_ptr<DeleteBitmap> delete_bitmap;
635
};
636
637
// used for controll compaction
638
struct VersionWithTime {
639
    std::atomic<int64_t> version;
640
    int64_t update_ts;
641
642
38.0k
    VersionWithTime() : version(0), update_ts(MonotonicMillis()) {}
643
644
40.9k
    void update_version_monoto(int64_t new_version) {
645
40.9k
        int64_t cur_version = version.load(std::memory_order_relaxed);
646
40.9k
        while (cur_version < new_version) {
647
40.9k
            if (version.compare_exchange_strong(cur_version, new_version, std::memory_order_relaxed,
648
40.9k
                                                std::memory_order_relaxed)) {
649
40.9k
                update_ts = MonotonicMillis();
650
40.9k
                break;
651
40.9k
            }
652
40.9k
        }
653
40.9k
    }
654
};
655
} // namespace doris
656
657
// This intended to be a "good" hash function.  It may change from time to time.
658
template <>
659
struct std::hash<doris::RowsetId> {
660
6.19M
    size_t operator()(const doris::RowsetId& rowset_id) const {
661
6.19M
        size_t seed = 0;
662
6.19M
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.hi, sizeof(rowset_id.hi),
663
6.19M
                                                 seed);
664
6.19M
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.mi, sizeof(rowset_id.mi),
665
6.19M
                                                 seed);
666
6.19M
        seed = doris::HashUtil::xxHash64WithSeed((const char*)&rowset_id.lo, sizeof(rowset_id.lo),
667
6.19M
                                                 seed);
668
6.19M
        return seed;
669
6.19M
    }
670
};