Coverage Report

Created: 2026-08-16 11:30

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
class VariantStatsCaculator;
64
65
struct SegmentWriterOptions {
66
    uint32_t num_rows_per_block = 1024;
67
    uint32_t max_rows_per_segment = UINT32_MAX;
68
    bool enable_unique_key_merge_on_write = false;
69
    CompressionTypePB compression_type = UNKNOWN_COMPRESSION;
70
71
    RowsetWriterContext* rowset_ctx = nullptr;
72
    DataWriteType write_type = DataWriteType::TYPE_DEFAULT;
73
    std::shared_ptr<MowContext> mow_ctx;
74
};
75
76
using TabletSharedPtr = std::shared_ptr<Tablet>;
77
78
class SegmentWriter {
79
public:
80
    explicit SegmentWriter(io::FileWriter* file_writer, uint32_t segment_id,
81
                           TabletSchemaSPtr tablet_schema, BaseTabletSPtr tablet, DataDir* data_dir,
82
                           const SegmentWriterOptions& opts, IndexFileWriter* inverted_file_writer);
83
    virtual ~SegmentWriter();
84
85
    virtual Status init();
86
87
    // for vertical compaction
88
    virtual Status init(const std::vector<uint32_t>& col_ids, bool has_key);
89
90
    virtual Status append_block(const Block* block, size_t row_pos, size_t num_rows);
91
92
    int64_t max_row_to_add(size_t row_avg_size_in_bytes);
93
94
    uint64_t estimate_segment_size();
95
96
28.8k
    uint32_t num_rows_written() const { return _num_rows_written; }
97
98
30.4k
    uint32_t row_count() const { return _row_count; }
99
100
    Status finalize(uint64_t* segment_file_size, uint64_t* index_size,
101
                    SegmentIndexFileCacheInfo* index_file_cache_info = nullptr);
102
103
12.6k
    uint32_t get_segment_id() const { return _segment_id; }
104
105
    Status finalize_columns_data();
106
    Status finalize_columns_index(uint64_t* index_size);
107
    Status finalize_footer(uint64_t* segment_file_size,
108
                           SegmentIndexFileCacheInfo* index_file_cache_info = nullptr);
109
110
    void init_column_meta(ColumnMetaPB* meta, uint32_t column_id, const TabletColumn& column,
111
                          const ColumnWriterOptions& opts);
112
    Slice min_encoded_key();
113
    Slice max_encoded_key();
114
115
0
    bool is_unique_key() { return _tablet_schema->keys_type() == UNIQUE_KEYS; }
116
117
    void clear();
118
119
6.24k
    Status close_inverted_index(int64_t* inverted_index_file_size) {
120
        // no inverted index
121
6.24k
        if (_index_file_writer == nullptr) {
122
5.66k
            *inverted_index_file_size = 0;
123
5.66k
            return Status::OK();
124
5.66k
        }
125
580
        RETURN_IF_ERROR(_index_file_writer->begin_close());
126
580
        *inverted_index_file_size = _index_file_writer->get_index_file_total_size();
127
580
        return Status::OK();
128
580
    }
129
130
0
    uint64_t primary_keys_size() const { return _primary_keys_size; }
131
132
private:
133
    friend class TestSegmentWriter;
134
    DISALLOW_COPY_AND_ASSIGN(SegmentWriter);
135
    Status _create_column_writer(uint32_t cid, const TabletColumn& column,
136
                                 const TabletSchemaSPtr& schema);
137
    Status _create_writers(const TabletSchemaSPtr& tablet_schema,
138
                           const std::vector<uint32_t>& col_ids);
139
    Status _write_data();
140
    Status _write_ordinal_index();
141
    Status _write_zone_map();
142
    Status _write_inverted_index();
143
    Status _write_ann_index();
144
    Status _write_bloom_filter_index();
145
    Status _write_short_key_index();
146
    Status _write_primary_key_index();
147
    Status _write_footer();
148
    Status _write_raw_data(const std::vector<Slice>& slices);
149
    void set_min_max_key(const Slice& key);
150
    void set_min_key(const Slice& key);
151
    void set_max_key(const Slice& key);
152
    Status _generate_primary_key_index(
153
            const std::vector<IOlapColumnDataAccessor*>& primary_key_columns,
154
            IOlapColumnDataAccessor* seq_column, size_t num_rows, bool need_sort);
155
    Status _generate_short_key_index(std::vector<IOlapColumnDataAccessor*>& key_columns,
156
                                     size_t num_rows, const std::vector<size_t>& short_key_pos);
157
412k
    bool _is_mow() {
158
412k
        return _tablet_schema->keys_type() == UNIQUE_KEYS && _opts.enable_unique_key_merge_on_write;
159
412k
    }
160
195k
    bool _is_mow_with_cluster_key() {
161
195k
        return _is_mow() && !_tablet_schema->cluster_key_uids().empty();
162
195k
    }
163
164
protected:
165
    // Build key index for derived writers that override append_block.
166
    Status build_key_index(std::vector<IOlapColumnDataAccessor*>& key_columns,
167
                           IOlapColumnDataAccessor* seq_column, size_t num_rows);
168
169
    uint32_t _segment_id;
170
    TabletSchemaSPtr _tablet_schema;
171
    BaseTabletSPtr _tablet;
172
    DataDir* _data_dir = nullptr;
173
    SegmentWriterOptions _opts;
174
175
    // Not owned. owned by RowsetWriter or SegmentFlusher
176
    io::FileWriter* _file_writer = nullptr;
177
    // Not owned. owned by RowsetWriter or SegmentFlusher
178
    IndexFileWriter* _index_file_writer = nullptr;
179
180
    SegmentFooterPB _footer;
181
    SegmentIndexFileCacheInfo _index_file_cache_info;
182
    size_t _num_short_key_columns;
183
184
    std::unique_ptr<ShortKeyIndexBuilder> _short_key_index_builder;
185
    std::unique_ptr<PrimaryKeyIndexBuilder> _primary_key_index_builder;
186
    std::vector<std::unique_ptr<ColumnWriter>> _column_writers;
187
    std::unique_ptr<MemTracker> _mem_tracker;
188
189
    std::unique_ptr<OlapBlockDataConvertor> _olap_data_convertor;
190
    // used for building short key index or primary key index during vectorized write.
191
    // NOTE: must stay declared after _tablet_schema and _opts, the constructor
192
    // init list reads both through _is_mow().
193
    RowKeyEncoder _key_encoder;
194
    size_t _short_key_row_pos = 0;
195
196
    std::vector<uint32_t> _column_ids;
197
    bool _has_key = true;
198
    // _num_rows_written means row count already written in this current column group
199
    uint32_t _num_rows_written = 0;
200
201
    // _row_count means total row count of this segment
202
    // In vertical compaction row count is recorded when key columns group finish
203
    //  and _num_rows_written will be updated in value column group
204
    uint32_t _row_count = 0;
205
206
    bool _is_first_row = true;
207
    faststring _min_key;
208
    faststring _max_key;
209
210
    std::shared_ptr<MowContext> _mow_context;
211
    std::vector<std::string> _primary_keys;
212
    uint64_t _primary_keys_size = 0;
213
    // variant statistics calculator for efficient stats collection
214
    std::unique_ptr<VariantStatsCaculator> _variant_stats_calculator;
215
};
216
217
} // namespace segment_v2
218
} // namespace doris