Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions be/src/exec/operator/scan_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,11 @@ TPushAggOp::type ScanLocalState<Derived>::get_push_down_agg_type() {
return _parent->cast<typename Derived::Parent>()._push_down_agg_type;
}

template <typename Derived>
std::optional<int32_t> ScanLocalState<Derived>::get_count_non_null_slot_id() {
return _parent->cast<typename Derived::Parent>()._count_non_null_slot_id;
}

template <typename Derived>
int64_t ScanLocalState<Derived>::limit_per_scanner() {
return _parent->cast<typename Derived::Parent>()._limit_per_scanner;
Expand Down Expand Up @@ -1231,6 +1236,9 @@ Status ScanOperatorX<LocalStateType>::init(const TPlanNode& tnode, RuntimeState*
} else {
_push_down_agg_type = TPushAggOp::type::NONE;
}
if (tnode.__isset.file_scan_node && tnode.file_scan_node.__isset.count_non_null_slot_id) {
_count_non_null_slot_id = tnode.file_scan_node.count_non_null_slot_id;
}

if (tnode.__isset.topn_filter_source_node_ids) {
_topn_filter_source_node_ids = tnode.topn_filter_source_node_ids;
Expand Down
5 changes: 5 additions & 0 deletions be/src/exec/operator/scan_operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include <cstdint>
#include <optional>
#include <set>
#include <string>

Expand Down Expand Up @@ -74,6 +75,7 @@ class ScanLocalStateBase : public PipelineXLocalState<> {
virtual void set_scan_ranges(RuntimeState* state,
const std::vector<TScanRangeParams>& scan_ranges) = 0;
virtual TPushAggOp::type get_push_down_agg_type() = 0;
virtual std::optional<int32_t> get_count_non_null_slot_id() = 0;

// If scan operator is serial operator(like topn), its real parallelism is 1.
// Otherwise, its real parallelism is query_parallel_instance_num.
Expand Down Expand Up @@ -252,6 +254,7 @@ class ScanLocalState : public ScanLocalStateBase {
const std::vector<TScanRangeParams>& scan_ranges) override {}

TPushAggOp::type get_push_down_agg_type() override;
std::optional<int32_t> get_count_non_null_slot_id() override;

std::vector<Dependency*> execution_dependencies() override {
if (_filter_dependencies.empty()) {
Expand Down Expand Up @@ -386,6 +389,7 @@ class ScanOperatorX : public OperatorX<LocalStateType> {
}

TPushAggOp::type get_push_down_agg_type() { return _push_down_agg_type; }
std::optional<int32_t> get_count_non_null_slot_id() const { return _count_non_null_slot_id; }

DataDistribution required_data_distribution(RuntimeState* /*state*/) const override {
if (OperatorX<LocalStateType>::is_serial_operator()) {
Expand Down Expand Up @@ -451,6 +455,7 @@ class ScanOperatorX : public OperatorX<LocalStateType> {
std::vector<TRuntimeFilterDesc> _runtime_filter_descs;

TPushAggOp::type _push_down_agg_type;
std::optional<int32_t> _count_non_null_slot_id;

// Record the value of the aggregate function 'count' from doris's be
int64_t _push_down_count = -1;
Expand Down
14 changes: 13 additions & 1 deletion be/src/exec/scan/file_scanner_v2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,16 @@ Status FileScannerV2::_init_table_reader(const TFileRangeDesc& range) {

VExprContextSPtrs table_conjuncts;
RETURN_IF_ERROR(_build_table_conjuncts(&table_conjuncts));
std::optional<format::GlobalIndex> count_non_null_global_index;
if (_local_state->get_count_non_null_slot_id().has_value()) {
const auto target =
_slot_id_to_global_index.find(*_local_state->get_count_non_null_slot_id());
if (target == _slot_id_to_global_index.end()) {
return Status::InternalError("Unknown COUNT_NON_NULL target slot {}",
*_local_state->get_count_non_null_slot_id());
}
count_non_null_global_index = target->second;
}
RETURN_IF_ERROR(_table_reader->init({
.projected_columns = _projected_columns,
.conjuncts = std::move(table_conjuncts),
Expand All @@ -458,6 +468,7 @@ Status FileScannerV2::_init_table_reader(const TFileRangeDesc& range) {
.scanner_profile = _local_state->scanner_profile(),
.file_slot_descs = &_file_slot_descs,
.push_down_agg_type = _local_state->get_push_down_agg_type(),
.count_non_null_global_index = count_non_null_global_index,
.condition_cache_digest = _local_state->get_condition_cache_digest(),
}));
return Status::OK();
Expand Down Expand Up @@ -800,7 +811,8 @@ bool FileScannerV2::_should_run_adaptive_batch_size() const {
// COUNT pushdown emits synthetic rows from file metadata and does not materialize file columns,
// so there is no useful row-width sample to learn from.
return _block_size_predictor != nullptr &&
_local_state->get_push_down_agg_type() != TPushAggOp::type::COUNT;
_local_state->get_push_down_agg_type() != TPushAggOp::type::COUNT &&
_local_state->get_push_down_agg_type() != TPushAggOp::type::COUNT_NON_NULL;
}

size_t FileScannerV2::_predict_reader_batch_rows() {
Expand Down
8 changes: 7 additions & 1 deletion be/src/format_v2/orc/orc_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,7 @@ Status OrcReader::get_aggregate_result(const format::FileAggregateRequest& reque
result->count = 0;
result->columns.clear();
if (request.agg_type != TPushAggOp::type::COUNT &&
request.agg_type != TPushAggOp::type::COUNT_NON_NULL &&
request.agg_type != TPushAggOp::type::MINMAX) {
return Status::NotSupported("Unsupported ORC aggregate pushdown type {}", request.agg_type);
}
Expand Down Expand Up @@ -1984,8 +1985,13 @@ Status OrcReader::get_aggregate_result(const format::FileAggregateRequest& reque
result->count += cast_set<int64_t>(stripe_information->getNumberOfRows());
}

if (request.agg_type == TPushAggOp::type::COUNT) {
if (request.agg_type == TPushAggOp::type::COUNT ||
request.agg_type == TPushAggOp::type::COUNT_NON_NULL) {
if (request.columns.empty()) {
if (request.agg_type == TPushAggOp::type::COUNT_NON_NULL) {
return Status::InvalidArgument(
"ORC COUNT_NON_NULL pushdown requires one count column");
}
return Status::OK();
}
if (request.columns.size() != 1) {
Expand Down
17 changes: 11 additions & 6 deletions be/src/format_v2/parquet/parquet_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ Status ParquetReader::get_aggregate_result(const format::FileAggregateRequest& r
result->count = 0;
result->columns.clear();
if (request.agg_type != TPushAggOp::type::COUNT &&
request.agg_type != TPushAggOp::type::COUNT_NON_NULL &&
request.agg_type != TPushAggOp::type::MINMAX) {
return Status::NotSupported("Unsupported parquet aggregate pushdown type {}",
request.agg_type);
Expand All @@ -605,8 +606,13 @@ Status ParquetReader::get_aggregate_result(const format::FileAggregateRequest& r
DORIS_CHECK(row_group_metadata != nullptr);
result->count += row_group_metadata->num_rows();
}
if (request.agg_type == TPushAggOp::type::COUNT) {
if (request.agg_type == TPushAggOp::type::COUNT ||
request.agg_type == TPushAggOp::type::COUNT_NON_NULL) {
if (request.columns.empty()) {
if (request.agg_type == TPushAggOp::type::COUNT_NON_NULL) {
return Status::InvalidArgument(
"Parquet COUNT_NON_NULL pushdown requires one count column");
}
return Status::OK();
}
if (request.columns.size() != 1) {
Expand Down Expand Up @@ -654,11 +660,10 @@ Status ParquetReader::get_aggregate_result(const format::FileAggregateRequest& r
while (range_rows_read < selected_range.length) {
const int64_t batch_rows =
std::min<int64_t>(_batch_size, selected_range.length - range_rows_read);
// COUNT(col) only needs the top-level NULL state. The shape reader loads
// def/rep levels from one representative leaf and does not build value_indices
// or values_column. MAP chooses the key leaf; ARRAY/STRUCT may choose a string
// leaf, but the levels-only protocol still avoids Doris-side string
// materialization for that leaf.
// COUNT(col) only needs the top-level NULL state. The shape reader keeps one
// def/rep pair per top-level row and discards physical values. Binary leaves
// use lightweight ByteArray cursors, so neither Arrow binary builders nor
// Doris string columns are materialized.
RETURN_IF_ERROR(_stop_status_if_requested(
shape_reader->load_nested_levels_batch(batch_rows)));
_record_scan_rows(batch_rows);
Expand Down
Loading
Loading