Coverage Report

Created: 2026-08-14 19:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/segment/segment_writer.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 <butil/macros.h>
21
#include <gen_cpp/olap_file.pb.h>
22
#include <gen_cpp/segment_v2.pb.h>
23
#include <stddef.h>
24
25
#include <cstdint>
26
#include <map>
27
#include <memory> // unique_ptr
28
#include <string>
29
#include <vector>
30
31
#include "common/status.h" // Status
32
#include "storage/index/index_file_writer.h"
33
#include "storage/key/row_key_encoder.h"
34
#include "storage/olap_define.h"
35
#include "storage/segment/column_writer.h"
36
#include "storage/segment/segment_index_file_cache_loader.h"
37
#include "storage/tablet/tablet.h"
38
#include "storage/tablet/tablet_schema.h"
39
#include "util/faststring.h"
40
#include "util/slice.h"
41
42
namespace doris {
43
class Block;
44
class IOlapColumnDataAccessor;
45
class OlapBlockDataConvertor;
46
47
// TODO(lingbin): Should be a conf that can be dynamically adjusted, or a member in the context
48
const uint32_t MAX_SEGMENT_SIZE = static_cast<uint32_t>(OLAP_MAX_COLUMN_SEGMENT_FILE_SIZE *
49
                                                        OLAP_COLUMN_FILE_SEGMENT_SIZE_SCALE);
50
class DataDir;
51
class MemTracker;
52
class ShortKeyIndexBuilder;
53
class PrimaryKeyIndexBuilder;
54
class KeyCoder;
55
struct RowsetWriterContext;
56
57
namespace io {
58
class FileWriter;
59
} // namespace io
60
61
namespace segment_v2 {
62
63
extern const char* k_segment_magic;
64
extern const uint32_t k_segment_magic_length;
65
66
class VariantStatsCaculator;
67
68
struct SegmentWriterOptions {
69
    uint32_t num_rows_per_block = 1024;
70
    uint32_t max_rows_per_segment = UINT32_MAX;
71
    bool enable_unique_key_merge_on_write = false;
72
    CompressionTypePB compression_type = UNKNOWN_COMPRESSION;
73
74
    RowsetWriterContext* rowset_ctx = nullptr;
75
    DataWriteType write_type = DataWriteType::TYPE_DEFAULT;
76
    std::shared_ptr<MowContext> mow_ctx;
77
};
78
79
using TabletSharedPtr = std::shared_ptr<Tablet>;
80
81
class SegmentWriter {
82
public:
83
    explicit SegmentWriter(io::FileWriter* file_writer, uint32_t segment_id,
84
                           TabletSchemaSPtr tablet_schema, BaseTabletSPtr tablet, DataDir* data_dir,
85
                           const SegmentWriterOptions& opts, IndexFileWriter* inverted_file_writer);
86
    virtual ~SegmentWriter();
87
88
    virtual Status init();
89
90
    // for vertical compaction
91
    virtual Status init(const std::vector<uint32_t>& col_ids, bool has_key);
92
93
    virtual Status append_block(const Block* block, size_t row_pos, size_t num_rows);
94
95
    int64_t max_row_to_add(size_t row_avg_size_in_bytes);
96
97
    uint64_t estimate_segment_size();
98
99
8.30k
    uint32_t num_rows_written() const { return _num_rows_written; }
100
101
5.43k
    uint32_t row_count() const { return _row_count; }
102
103
    Status finalize(uint64_t* segment_file_size, uint64_t* index_size,
104
                    SegmentIndexFileCacheInfo* index_file_cache_info = nullptr);
105
106
3.38k
    uint32_t get_segment_id() const { return _segment_id; }
107
108
    Status finalize_columns_data();
109
    Status finalize_columns_index(uint64_t* index_size);
110
    Status finalize_footer(uint64_t* segment_file_size,
111
                           SegmentIndexFileCacheInfo* index_file_cache_info = nullptr);
112
113
    void init_column_meta(ColumnMetaPB* meta, uint32_t column_id, const TabletColumn& column,
114
                          const ColumnWriterOptions& opts);
115
    Slice min_encoded_key();
116
    Slice max_encoded_key();
117
118
0
    bool is_unique_key() { return _tablet_schema->keys_type() == UNIQUE_KEYS; }
119
120
    void clear();
121
122
2.17k
    Status close_inverted_index(int64_t* inverted_index_file_size) {
123
        // no inverted index
124
2.17k
        if (_index_file_writer == nullptr) {
125
1.87k
            *inverted_index_file_size = 0;
126
1.87k
            return Status::OK();
127
1.87k
        }
128
302
        RETURN_IF_ERROR(_index_file_writer->begin_close());
129
302
        *inverted_index_file_size = _index_file_writer->get_index_file_total_size();
130
302
        return Status::OK();
131
302
    }
132
133
0
    uint64_t primary_keys_size() const { return _primary_keys_size; }
134
135
private:
136
    friend class TestSegmentWriter;
137
    DISALLOW_COPY_AND_ASSIGN(SegmentWriter);
138
    Status _create_column_writer(uint32_t cid, const TabletColumn& column,
139
                                 const TabletSchemaSPtr& schema);
140
    Status _create_writers(const TabletSchemaSPtr& tablet_schema,
141
                           const std::vector<uint32_t>& col_ids);
142
    Status _write_data();
143
    Status _write_ordinal_index();
144
    Status _write_zone_map();
145
    Status _write_inverted_index();
146
    Status _write_ann_index();
147
    Status _write_bloom_filter_index();
148
    Status _write_short_key_index();
149
    Status _write_primary_key_index();
150
    Status _write_footer();
151
    Status _write_raw_data(const std::vector<Slice>& slices);
152
    void set_min_max_key(const Slice& key);
153
    void set_min_key(const Slice& key);
154
    void set_max_key(const Slice& key);
155
    Status _generate_primary_key_index(
156
            const std::vector<IOlapColumnDataAccessor*>& primary_key_columns,
157
            IOlapColumnDataAccessor* seq_column, size_t num_rows, bool need_sort);
158
    Status _generate_short_key_index(std::vector<IOlapColumnDataAccessor*>& key_columns,
159
                                     size_t num_rows, const std::vector<size_t>& short_key_pos);
160
340k
    bool _is_mow() {
161
340k
        return _tablet_schema->keys_type() == UNIQUE_KEYS && _opts.enable_unique_key_merge_on_write;
162
340k
    }
163
166k
    bool _is_mow_with_cluster_key() {
164
166k
        return _is_mow() && !_tablet_schema->cluster_key_uids().empty();
165
166k
    }
166
167
protected:
168
    // Build key index for derived writers that override append_block.
169
    Status build_key_index(std::vector<IOlapColumnDataAccessor*>& key_columns,
170
                           IOlapColumnDataAccessor* seq_column, size_t num_rows);
171
172
    uint32_t _segment_id;
173
    TabletSchemaSPtr _tablet_schema;
174
    BaseTabletSPtr _tablet;
175
    DataDir* _data_dir = nullptr;
176
    SegmentWriterOptions _opts;
177
178
    // Not owned. owned by RowsetWriter or SegmentFlusher
179
    io::FileWriter* _file_writer = nullptr;
180
    // Not owned. owned by RowsetWriter or SegmentFlusher
181
    IndexFileWriter* _index_file_writer = nullptr;
182
183
    SegmentFooterPB _footer;
184
    SegmentIndexFileCacheInfo _index_file_cache_info;
185
    size_t _num_short_key_columns;
186
187
    std::unique_ptr<ShortKeyIndexBuilder> _short_key_index_builder;
188
    std::unique_ptr<PrimaryKeyIndexBuilder> _primary_key_index_builder;
189
    std::vector<std::unique_ptr<ColumnWriter>> _column_writers;
190
    std::unique_ptr<MemTracker> _mem_tracker;
191
192
    std::unique_ptr<OlapBlockDataConvertor> _olap_data_convertor;
193
    // used for building short key index or primary key index during vectorized write.
194
    // NOTE: must stay declared after _tablet_schema and _opts, the constructor
195
    // init list reads both through _is_mow().
196
    RowKeyEncoder _key_encoder;
197
    size_t _short_key_row_pos = 0;
198
199
    std::vector<uint32_t> _column_ids;
200
    bool _has_key = true;
201
    // _num_rows_written means row count already written in this current column group
202
    uint32_t _num_rows_written = 0;
203
204
    // _row_count means total row count of this segment
205
    // In vertical compaction row count is recorded when key columns group finish
206
    //  and _num_rows_written will be updated in value column group
207
    uint32_t _row_count = 0;
208
209
    bool _is_first_row = true;
210
    faststring _min_key;
211
    faststring _max_key;
212
213
    std::shared_ptr<MowContext> _mow_context;
214
    std::vector<std::string> _primary_keys;
215
    uint64_t _primary_keys_size = 0;
216
    // variant statistics calculator for efficient stats collection
217
    std::unique_ptr<VariantStatsCaculator> _variant_stats_calculator;
218
};
219
220
} // namespace segment_v2
221
} // namespace doris