Coverage Report

Created: 2026-07-23 22:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/format_v2/parquet/parquet_statistics.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
//   http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing,
10
// software distributed under the License is distributed on an
11
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
12
// KIND, either express or implied.  See the License for the
13
// specific language governing permissions and limitations
14
// under the License.
15
16
#pragma once
17
18
#include <gen_cpp/parquet_types.h>
19
20
#include <cstddef>
21
#include <cstdint>
22
#include <map>
23
#include <memory>
24
#include <string>
25
#include <unordered_map>
26
#include <vector>
27
28
#include "common/status.h"
29
#include "core/field.h"
30
#include "core/string_ref.h"
31
#include "exprs/vexpr_fwd.h"
32
#include "format_v2/file_reader.h"
33
#include "format_v2/parquet/parquet_profile.h"
34
#include "format_v2/parquet/selection_vector.h"
35
36
namespace cctz {
37
class time_zone;
38
} // namespace cctz
39
40
namespace doris {
41
class RuntimeState;
42
namespace segment_v2 {
43
class BloomFilter;
44
struct ZoneMap;
45
} // namespace segment_v2
46
} // namespace doris
47
48
namespace doris::format::parquet {
49
50
struct ParquetColumnSchema;
51
struct ParquetFileContext;
52
struct ParquetTypeDescriptor;
53
54
namespace detail {
55
Status validate_native_bloom_filter_layout(int64_t offset, uint32_t header_size,
56
                                           int64_t payload_size, int64_t declared_length,
57
                                           size_t file_size);
58
bool can_use_native_footer_min_max(const ParquetTypeDescriptor& type_descriptor,
59
                                   const tparquet::Statistics& statistics,
60
                                   bool has_type_defined_order);
61
bool has_supported_type_defined_order(const tparquet::FileMetaData& metadata, int leaf_column_id);
62
tparquet::Statistics sanitize_native_footer_statistics(const ParquetTypeDescriptor& type_descriptor,
63
                                                       const tparquet::Statistics& statistics,
64
                                                       bool has_type_defined_order);
65
} // namespace detail
66
67
// ============================================================================
68
// ============================================================================
69
70
struct ParquetPruningStats {
71
    int64_t total_row_groups = 0;                    // total row groups in the file
72
    int64_t selected_row_groups = 0;                 // row groups selected after pruning
73
    int64_t filtered_row_groups_by_statistics = 0;   // row groups pruned by ZoneMap statistics
74
    int64_t filtered_row_groups_by_dictionary = 0;   // row groups pruned by dictionary
75
    int64_t filtered_row_groups_by_bloom_filter = 0; // row groups pruned by bloom filter
76
    int64_t filtered_row_groups_by_page_index = 0;   // row groups fully pruned by page index
77
    int64_t filtered_group_rows = 0;                 // rows in pruned row groups
78
    int64_t filtered_bytes = 0;                      // requested bytes in pruned row groups
79
    int64_t filtered_page_rows = 0;                  // rows pruned by page index
80
    int64_t selected_row_ranges = 0;                 // selected row range count
81
    int64_t page_index_read_calls = 0;               // Page Index read count
82
    int64_t bloom_filter_read_time = 0;              // Bloom filter read time (ns)
83
    int64_t row_group_filter_time = 0;               // row-group pruning time (ns)
84
    int64_t page_index_filter_time = 0;              // page-index pruning time (ns)
85
    int64_t read_page_index_time = 0;                // page-index read time (ns)
86
    int64_t parse_page_index_time = 0;               // lazy page-index materialization time (ns)
87
    int64_t expr_zonemap_unusable_evals = 0;         // VExpr ZoneMap unusable evaluations
88
    int64_t in_zonemap_point_check_count = 0;        // VExpr IN ZoneMap point checks
89
    int64_t in_zonemap_range_only_count = 0;         // VExpr IN ZoneMap range-only checks
90
};
91
92
struct ParquetColumnStatistics {
93
    Field min_value;             // column minimum value converted to Doris type
94
    Field max_value;             // column maximum value
95
    bool has_null = false;       // whether NULL exists
96
    bool has_not_null = false;   // whether non-NULL values exist
97
    bool has_null_count = false; // whether null_count is valid
98
    bool has_min_max = false;    // whether min/max is valid after conversion
99
100
0
    bool has_any_statistics() const { return has_null_count || has_min_max; }
101
};
102
103
struct NativeParquetPageIndex {
104
    tparquet::ColumnIndex column_index;
105
    tparquet::OffsetIndex offset_index;
106
};
107
108
enum class ParquetMetadataProbeMode {
109
    ALL,
110
    FOOTER_ONLY,
111
    EXPENSIVE_ONLY,
112
};
113
114
bool can_use_parquet_page_index(const format::FileScanRequest& request,
115
                                const RuntimeState* runtime_state);
116
117
// ============================================================================
118
// ============================================================================
119
//     VExpr ZoneMap(TransformColumnStatistics + evaluate_zonemap_filter)
120
//     -> page-index ZoneMap(evaluate_zonemap_filter)
121
//     dictionary(read_dictionary_words + evaluate_dictionary_filter)
122
//     -> bloom filter(evaluate_bloom_filter)
123
// ============================================================================
124
struct ParquetStatisticsUtils {
125
    static std::shared_ptr<segment_v2::ZoneMap> MakeZoneMap(
126
            const ParquetColumnStatistics& statistics);
127
128
    static ParquetColumnStatistics TransformColumnStatistics(
129
            const ParquetColumnSchema& column_schema, const tparquet::Statistics* statistics,
130
            int64_t column_value_count, const cctz::time_zone* timezone = nullptr);
131
132
    static bool NativeBloomFilterExcludes(const ParquetColumnSchema& column_schema, int slot_index,
133
                                          const VExprContextSPtrs& conjuncts,
134
                                          const segment_v2::BloomFilter& bloom_filter);
135
};
136
137
Status select_row_groups_by_metadata(
138
        const tparquet::FileMetaData& metadata,
139
        const std::vector<std::unique_ptr<ParquetColumnSchema>>& file_schema,
140
        const format::FileScanRequest& request, const std::vector<int>* candidate_row_groups,
141
        std::vector<int>* selected_row_groups, bool enable_bloom_filter,
142
        ParquetPruningStats* pruning_stats, const cctz::time_zone* timezone = nullptr,
143
        const RuntimeState* runtime_state = nullptr, ParquetFileContext* file_context = nullptr,
144
        const ParquetColumnReaderProfile& column_reader_profile = {},
145
        ParquetMetadataProbeMode probe_mode = ParquetMetadataProbeMode::ALL);
146
147
Status select_row_group_ranges_by_native_page_index(
148
        const tparquet::FileMetaData& metadata,
149
        const std::unordered_map<int, NativeParquetPageIndex>& page_indexes,
150
        const std::vector<std::unique_ptr<ParquetColumnSchema>>& file_schema,
151
        const format::FileScanRequest& request, int64_t row_group_rows,
152
        std::vector<RowRange>* selected_ranges, std::map<int, ParquetPageSkipPlan>* page_skip_plans,
153
        ParquetPruningStats* pruning_stats, const cctz::time_zone* timezone = nullptr,
154
        const RuntimeState* runtime_state = nullptr);
155
156
} // namespace doris::format::parquet