Refactoring the filtering conditions in the current ExecNode from an expression tree to an array can simplify the process of adding runtime filters. It eliminates the need for complex merge operations and removes the requirement for the frontend to combine expressions into a single entity. By representing the filtering conditions as an array, each condition can be treated individually, making it easier to add runtime filters without the need for complex merging logic. The array can store the individual conditions, and the runtime filter logic can iterate through the array to apply the filters as needed. This refactoring simplifies the codebase, improves readability, and reduces the complexity associated with handling filtering conditions and adding runtime filters. It separates the conditions into discrete entities, enabling more straightforward manipulation and management within the execution node.
619 lines
28 KiB
C++
619 lines
28 KiB
C++
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
#include "vec/exec/scan/new_olap_scanner.h"
|
|
|
|
#include <gen_cpp/Descriptors_types.h>
|
|
#include <gen_cpp/PlanNodes_types.h>
|
|
#include <gen_cpp/Types_types.h>
|
|
#include <glog/logging.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <iterator>
|
|
#include <ostream>
|
|
#include <set>
|
|
#include <shared_mutex>
|
|
|
|
#include "common/config.h"
|
|
#include "common/consts.h"
|
|
#include "common/logging.h"
|
|
#include "exec/olap_utils.h"
|
|
#include "exprs/function_filter.h"
|
|
#include "io/cache/block/block_file_cache_profile.h"
|
|
#include "io/io_common.h"
|
|
#include "olap/olap_common.h"
|
|
#include "olap/olap_tuple.h"
|
|
#include "olap/rowset/rowset.h"
|
|
#include "olap/rowset/rowset_meta.h"
|
|
#include "olap/storage_engine.h"
|
|
#include "olap/tablet_manager.h"
|
|
#include "olap/tablet_meta.h"
|
|
#include "runtime/descriptors.h"
|
|
#include "runtime/runtime_state.h"
|
|
#include "service/backend_options.h"
|
|
#include "util/doris_metrics.h"
|
|
#include "util/runtime_profile.h"
|
|
#include "vec/core/block.h"
|
|
#include "vec/exec/scan/new_olap_scan_node.h"
|
|
#include "vec/exec/scan/vscan_node.h"
|
|
#include "vec/exprs/vexpr_context.h"
|
|
#include "vec/olap/block_reader.h"
|
|
|
|
namespace doris::vectorized {
|
|
|
|
NewOlapScanner::NewOlapScanner(RuntimeState* state, NewOlapScanNode* parent, int64_t limit,
|
|
bool aggregation, const TPaloScanRange& scan_range,
|
|
const std::vector<OlapScanRange*>& key_ranges,
|
|
const std::vector<RowsetReaderSharedPtr>& rs_readers,
|
|
const std::vector<std::pair<int, int>>& rs_reader_seg_offsets,
|
|
bool need_agg_finalize, RuntimeProfile* profile)
|
|
: VScanner(state, static_cast<VScanNode*>(parent), limit, profile),
|
|
_aggregation(aggregation),
|
|
_need_agg_finalize(need_agg_finalize),
|
|
_version(-1),
|
|
_scan_range(scan_range),
|
|
_key_ranges(key_ranges) {
|
|
DCHECK(rs_readers.size() == rs_reader_seg_offsets.size());
|
|
_tablet_reader_params.rs_readers = rs_readers;
|
|
_tablet_reader_params.rs_readers_segment_offsets = rs_reader_seg_offsets;
|
|
_tablet_schema = std::make_shared<TabletSchema>();
|
|
_is_init = false;
|
|
}
|
|
|
|
static std::string read_columns_to_string(TabletSchemaSPtr tablet_schema,
|
|
const std::vector<uint32_t>& read_columns) {
|
|
// avoid too long for one line,
|
|
// it is hard to display in `show profile` stmt if one line is too long.
|
|
const int col_per_line = 10;
|
|
int i = 0;
|
|
std::string read_columns_string;
|
|
read_columns_string += "[";
|
|
for (auto it = read_columns.cbegin(); it != read_columns.cend(); it++) {
|
|
if (it != read_columns.cbegin()) {
|
|
read_columns_string += ", ";
|
|
}
|
|
read_columns_string += tablet_schema->columns().at(*it).name();
|
|
if (i >= col_per_line) {
|
|
read_columns_string += "\n";
|
|
i = 0;
|
|
} else {
|
|
++i;
|
|
}
|
|
}
|
|
read_columns_string += "]";
|
|
return read_columns_string;
|
|
}
|
|
|
|
Status NewOlapScanner::init() {
|
|
_is_init = true;
|
|
auto parent = static_cast<NewOlapScanNode*>(_parent);
|
|
RETURN_IF_ERROR(VScanner::prepare(_state, parent->_conjuncts));
|
|
|
|
for (auto& ctx : parent->_common_expr_ctxs_push_down) {
|
|
VExprContextSPtr context;
|
|
RETURN_IF_ERROR(ctx->clone(_state, context));
|
|
_common_expr_ctxs_push_down.emplace_back(context);
|
|
}
|
|
|
|
// set limit to reduce end of rowset and segment mem use
|
|
_tablet_reader = std::make_unique<BlockReader>();
|
|
_tablet_reader->set_batch_size(
|
|
_parent->limit() == -1
|
|
? _state->batch_size()
|
|
: std::min(static_cast<int64_t>(_state->batch_size()), _parent->limit()));
|
|
|
|
// Get olap table
|
|
TTabletId tablet_id = _scan_range.tablet_id;
|
|
_version = strtoul(_scan_range.version.c_str(), nullptr, 10);
|
|
{
|
|
auto [tablet, status] =
|
|
StorageEngine::instance()->tablet_manager()->get_tablet_and_status(tablet_id, true);
|
|
RETURN_IF_ERROR(status);
|
|
_tablet = std::move(tablet);
|
|
_tablet_schema->copy_from(*_tablet->tablet_schema());
|
|
|
|
TOlapScanNode& olap_scan_node = ((NewOlapScanNode*)_parent)->_olap_scan_node;
|
|
if (olap_scan_node.__isset.columns_desc && !olap_scan_node.columns_desc.empty() &&
|
|
olap_scan_node.columns_desc[0].col_unique_id >= 0) {
|
|
// Originally scanner get TabletSchema from tablet object in BE.
|
|
// To support lightweight schema change for adding / dropping columns,
|
|
// tabletschema is bounded to rowset and tablet's schema maybe outdated,
|
|
// so we have to use schema from a query plan witch FE puts it in query plans.
|
|
_tablet_schema->clear_columns();
|
|
for (const auto& column_desc : olap_scan_node.columns_desc) {
|
|
_tablet_schema->append_column(TabletColumn(column_desc));
|
|
}
|
|
}
|
|
|
|
if (olap_scan_node.__isset.indexes_desc) {
|
|
_tablet_schema->update_indexes_from_thrift(olap_scan_node.indexes_desc);
|
|
}
|
|
|
|
{
|
|
if (_output_tuple_desc->slots().back()->col_name() == BeConsts::ROWID_COL) {
|
|
// inject ROWID_COL
|
|
TabletColumn rowid_column;
|
|
rowid_column.set_is_nullable(false);
|
|
rowid_column.set_name(BeConsts::ROWID_COL);
|
|
// avoid column reader init error
|
|
rowid_column.set_has_default_value(true);
|
|
// fake unique id
|
|
rowid_column.set_unique_id(INT32_MAX);
|
|
rowid_column.set_aggregation_method(
|
|
FieldAggregationMethod::OLAP_FIELD_AGGREGATION_REPLACE);
|
|
rowid_column.set_type(FieldType::OLAP_FIELD_TYPE_STRING);
|
|
_tablet_schema->append_column(rowid_column);
|
|
}
|
|
}
|
|
|
|
{
|
|
std::shared_lock rdlock(_tablet->get_header_lock());
|
|
if (_tablet_reader_params.rs_readers.empty()) {
|
|
const RowsetSharedPtr rowset = _tablet->rowset_with_max_version();
|
|
if (rowset == nullptr) {
|
|
std::stringstream ss;
|
|
ss << "fail to get latest version of tablet: " << tablet_id;
|
|
LOG(WARNING) << ss.str();
|
|
return Status::InternalError(ss.str());
|
|
}
|
|
|
|
// acquire tablet rowset readers at the beginning of the scan node
|
|
// to prevent this case: when there are lots of olap scanners to run for example 10000
|
|
// the rowsets maybe compacted when the last olap scanner starts
|
|
Version rd_version(0, _version);
|
|
Status acquire_reader_st =
|
|
_tablet->capture_rs_readers(rd_version, &_tablet_reader_params.rs_readers);
|
|
if (!acquire_reader_st.ok()) {
|
|
LOG(WARNING) << "fail to init reader.res=" << acquire_reader_st;
|
|
std::stringstream ss;
|
|
ss << "failed to initialize storage reader. tablet=" << _tablet->full_name()
|
|
<< ", res=" << acquire_reader_st
|
|
<< ", backend=" << BackendOptions::get_localhost();
|
|
return Status::InternalError(ss.str());
|
|
}
|
|
}
|
|
|
|
// Initialize tablet_reader_params
|
|
RETURN_IF_ERROR(_init_tablet_reader_params(_key_ranges, parent->_olap_filters,
|
|
parent->_filter_predicates,
|
|
parent->_push_down_functions));
|
|
}
|
|
}
|
|
|
|
// add read columns in profile
|
|
if (_state->enable_profile()) {
|
|
_profile->add_info_string("ReadColumns",
|
|
read_columns_to_string(_tablet_schema, _return_columns));
|
|
}
|
|
|
|
return Status::OK();
|
|
}
|
|
|
|
Status NewOlapScanner::open(RuntimeState* state) {
|
|
RETURN_IF_ERROR(VScanner::open(state));
|
|
|
|
auto res = _tablet_reader->init(_tablet_reader_params);
|
|
if (!res.ok()) {
|
|
std::stringstream ss;
|
|
ss << "failed to initialize storage reader. tablet="
|
|
<< _tablet_reader_params.tablet->full_name() << ", res=" << res
|
|
<< ", backend=" << BackendOptions::get_localhost();
|
|
return Status::InternalError(ss.str());
|
|
}
|
|
|
|
return Status::OK();
|
|
}
|
|
|
|
void NewOlapScanner::set_compound_filters(const std::vector<TCondition>& compound_filters) {
|
|
_compound_filters = compound_filters;
|
|
}
|
|
|
|
// it will be called under tablet read lock because capture rs readers need
|
|
Status NewOlapScanner::_init_tablet_reader_params(
|
|
const std::vector<OlapScanRange*>& key_ranges, const std::vector<TCondition>& filters,
|
|
const FilterPredicates& filter_predicates,
|
|
const std::vector<FunctionFilter>& function_filters) {
|
|
// if the table with rowset [0-x] or [0-1] [2-y], and [0-1] is empty
|
|
bool single_version =
|
|
(_tablet_reader_params.rs_readers.size() == 1 &&
|
|
_tablet_reader_params.rs_readers[0]->rowset()->start_version() == 0 &&
|
|
!_tablet_reader_params.rs_readers[0]
|
|
->rowset()
|
|
->rowset_meta()
|
|
->is_segments_overlapping()) ||
|
|
(_tablet_reader_params.rs_readers.size() == 2 &&
|
|
_tablet_reader_params.rs_readers[0]->rowset()->rowset_meta()->num_rows() == 0 &&
|
|
_tablet_reader_params.rs_readers[1]->rowset()->start_version() == 2 &&
|
|
!_tablet_reader_params.rs_readers[1]
|
|
->rowset()
|
|
->rowset_meta()
|
|
->is_segments_overlapping());
|
|
auto real_parent = reinterpret_cast<NewOlapScanNode*>(_parent);
|
|
if (_state->skip_storage_engine_merge()) {
|
|
_tablet_reader_params.direct_mode = true;
|
|
_aggregation = true;
|
|
} else {
|
|
_tablet_reader_params.direct_mode =
|
|
_aggregation || single_version ||
|
|
real_parent->_olap_scan_node.__isset.push_down_agg_type_opt;
|
|
}
|
|
|
|
RETURN_IF_ERROR(_init_return_columns());
|
|
|
|
_tablet_reader_params.tablet = _tablet;
|
|
_tablet_reader_params.tablet_schema = _tablet_schema;
|
|
_tablet_reader_params.reader_type = ReaderType::READER_QUERY;
|
|
_tablet_reader_params.aggregation = _aggregation;
|
|
if (real_parent->_olap_scan_node.__isset.push_down_agg_type_opt) {
|
|
_tablet_reader_params.push_down_agg_type_opt =
|
|
real_parent->_olap_scan_node.push_down_agg_type_opt;
|
|
}
|
|
_tablet_reader_params.version = Version(0, _version);
|
|
|
|
// TODO: If a new runtime filter arrives after `_conjuncts` move to `_common_expr_ctxs_push_down`,
|
|
if (_common_expr_ctxs_push_down.empty()) {
|
|
for (auto& conjunct : _conjuncts) {
|
|
_tablet_reader_params.remaining_conjunct_roots.emplace_back(conjunct->root());
|
|
}
|
|
} else {
|
|
for (auto& ctx : _common_expr_ctxs_push_down) {
|
|
_tablet_reader_params.remaining_conjunct_roots.emplace_back(ctx->root());
|
|
}
|
|
}
|
|
|
|
_tablet_reader_params.common_expr_ctxs_push_down = _common_expr_ctxs_push_down;
|
|
_tablet_reader_params.output_columns = ((NewOlapScanNode*)_parent)->_maybe_read_column_ids;
|
|
|
|
// Condition
|
|
for (auto& filter : filters) {
|
|
if (is_match_condition(filter.condition_op) &&
|
|
!_tablet_schema->has_inverted_index(
|
|
_tablet_schema->column(filter.column_name).unique_id())) {
|
|
return Status::NotSupported("Match query must with inverted index, column `" +
|
|
filter.column_name + "` is not inverted index column");
|
|
}
|
|
_tablet_reader_params.conditions.push_back(filter);
|
|
}
|
|
|
|
for (auto& filter : _compound_filters) {
|
|
if (is_match_condition(filter.condition_op) &&
|
|
!_tablet_schema->has_inverted_index(
|
|
_tablet_schema->column(filter.column_name).unique_id())) {
|
|
return Status::NotSupported("Match query must with inverted index, column `" +
|
|
filter.column_name + "` is not inverted index column");
|
|
}
|
|
}
|
|
|
|
std::copy(_compound_filters.cbegin(), _compound_filters.cend(),
|
|
std::inserter(_tablet_reader_params.conditions_except_leafnode_of_andnode,
|
|
_tablet_reader_params.conditions_except_leafnode_of_andnode.begin()));
|
|
|
|
std::copy(filter_predicates.bloom_filters.cbegin(), filter_predicates.bloom_filters.cend(),
|
|
std::inserter(_tablet_reader_params.bloom_filters,
|
|
_tablet_reader_params.bloom_filters.begin()));
|
|
std::copy(filter_predicates.bitmap_filters.cbegin(), filter_predicates.bitmap_filters.cend(),
|
|
std::inserter(_tablet_reader_params.bitmap_filters,
|
|
_tablet_reader_params.bitmap_filters.begin()));
|
|
|
|
std::copy(filter_predicates.in_filters.cbegin(), filter_predicates.in_filters.cend(),
|
|
std::inserter(_tablet_reader_params.in_filters,
|
|
_tablet_reader_params.in_filters.begin()));
|
|
|
|
std::copy(function_filters.cbegin(), function_filters.cend(),
|
|
std::inserter(_tablet_reader_params.function_filters,
|
|
_tablet_reader_params.function_filters.begin()));
|
|
|
|
if (!_state->skip_delete_predicate()) {
|
|
auto& delete_preds = _tablet->delete_predicates();
|
|
std::copy(delete_preds.cbegin(), delete_preds.cend(),
|
|
std::inserter(_tablet_reader_params.delete_predicates,
|
|
_tablet_reader_params.delete_predicates.begin()));
|
|
}
|
|
|
|
// Merge the columns in delete predicate that not in latest schema in to current tablet schema
|
|
for (auto& del_pred_pb : _tablet_reader_params.delete_predicates) {
|
|
_tablet_schema->merge_dropped_columns(_tablet->tablet_schema(del_pred_pb->version()));
|
|
}
|
|
|
|
// Range
|
|
for (auto key_range : key_ranges) {
|
|
if (key_range->begin_scan_range.size() == 1 &&
|
|
key_range->begin_scan_range.get_value(0) == NEGATIVE_INFINITY) {
|
|
continue;
|
|
}
|
|
|
|
_tablet_reader_params.start_key_include = key_range->begin_include;
|
|
_tablet_reader_params.end_key_include = key_range->end_include;
|
|
|
|
_tablet_reader_params.start_key.push_back(key_range->begin_scan_range);
|
|
_tablet_reader_params.end_key.push_back(key_range->end_scan_range);
|
|
}
|
|
|
|
_tablet_reader_params.profile = _parent->runtime_profile();
|
|
_tablet_reader_params.runtime_state = _state;
|
|
|
|
_tablet_reader_params.origin_return_columns = &_return_columns;
|
|
_tablet_reader_params.tablet_columns_convert_to_null_set = &_tablet_columns_convert_to_null_set;
|
|
|
|
if (_tablet_reader_params.direct_mode) {
|
|
_tablet_reader_params.return_columns = _return_columns;
|
|
} else {
|
|
// we need to fetch all key columns to do the right aggregation on storage engine side.
|
|
for (size_t i = 0; i < _tablet_schema->num_key_columns(); ++i) {
|
|
_tablet_reader_params.return_columns.push_back(i);
|
|
}
|
|
for (auto index : _return_columns) {
|
|
if (_tablet_schema->column(index).is_key()) {
|
|
continue;
|
|
} else {
|
|
_tablet_reader_params.return_columns.push_back(index);
|
|
}
|
|
}
|
|
// expand the sequence column
|
|
if (_tablet_schema->has_sequence_col()) {
|
|
bool has_replace_col = false;
|
|
for (auto col : _return_columns) {
|
|
if (_tablet_schema->column(col).aggregation() ==
|
|
FieldAggregationMethod::OLAP_FIELD_AGGREGATION_REPLACE) {
|
|
has_replace_col = true;
|
|
break;
|
|
}
|
|
}
|
|
if (auto sequence_col_idx = _tablet_schema->sequence_col_idx();
|
|
has_replace_col && std::find(_return_columns.begin(), _return_columns.end(),
|
|
sequence_col_idx) == _return_columns.end()) {
|
|
_tablet_reader_params.return_columns.push_back(sequence_col_idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If a agg node is this scan node direct parent
|
|
// we will not call agg object finalize method in scan node,
|
|
// to avoid the unnecessary SerDe and improve query performance
|
|
_tablet_reader_params.need_agg_finalize = _need_agg_finalize;
|
|
|
|
if (!config::disable_storage_page_cache) {
|
|
_tablet_reader_params.use_page_cache = true;
|
|
}
|
|
|
|
if (_tablet->enable_unique_key_merge_on_write() && !_state->skip_delete_bitmap()) {
|
|
_tablet_reader_params.delete_bitmap = &_tablet->tablet_meta()->delete_bitmap();
|
|
}
|
|
|
|
if (!_state->skip_storage_engine_merge()) {
|
|
TOlapScanNode& olap_scan_node = ((NewOlapScanNode*)_parent)->_olap_scan_node;
|
|
// order by table keys optimization for topn
|
|
// will only read head/tail of data file since it's already sorted by keys
|
|
if (olap_scan_node.__isset.sort_info && olap_scan_node.sort_info.is_asc_order.size() > 0) {
|
|
_limit = _parent->_limit_per_scanner;
|
|
_tablet_reader_params.read_orderby_key = true;
|
|
if (!olap_scan_node.sort_info.is_asc_order[0]) {
|
|
_tablet_reader_params.read_orderby_key_reverse = true;
|
|
}
|
|
_tablet_reader_params.read_orderby_key_num_prefix_columns =
|
|
olap_scan_node.sort_info.is_asc_order.size();
|
|
_tablet_reader_params.read_orderby_key_limit = _limit;
|
|
_tablet_reader_params.filter_block_conjuncts = _conjuncts;
|
|
}
|
|
|
|
// runtime predicate push down optimization for topn
|
|
_tablet_reader_params.use_topn_opt =
|
|
((NewOlapScanNode*)_parent)->_olap_scan_node.use_topn_opt;
|
|
}
|
|
|
|
return Status::OK();
|
|
}
|
|
|
|
Status NewOlapScanner::_init_return_columns() {
|
|
for (auto slot : _output_tuple_desc->slots()) {
|
|
if (!slot->is_materialized()) {
|
|
continue;
|
|
}
|
|
if (!slot->need_materialize()) {
|
|
continue;
|
|
}
|
|
int32_t index = slot->col_unique_id() >= 0
|
|
? _tablet_schema->field_index(slot->col_unique_id())
|
|
: _tablet_schema->field_index(slot->col_name());
|
|
|
|
if (index < 0) {
|
|
std::stringstream ss;
|
|
ss << "field name is invalid. field=" << slot->col_name()
|
|
<< ", field_name_to_index=" << _tablet_schema->get_all_field_names();
|
|
return Status::InternalError(ss.str());
|
|
}
|
|
_return_columns.push_back(index);
|
|
if (slot->is_nullable() && !_tablet_schema->column(index).is_nullable()) {
|
|
_tablet_columns_convert_to_null_set.emplace(index);
|
|
}
|
|
}
|
|
|
|
if (_return_columns.empty()) {
|
|
return Status::InternalError("failed to build storage scanner, no materialized slot!");
|
|
}
|
|
return Status::OK();
|
|
}
|
|
|
|
doris::TabletStorageType NewOlapScanner::get_storage_type() {
|
|
int local_reader = 0;
|
|
for (const auto& reader : _tablet_reader_params.rs_readers) {
|
|
local_reader += reader->rowset()->is_local();
|
|
}
|
|
int total_reader = _tablet_reader_params.rs_readers.size();
|
|
|
|
if (local_reader == total_reader) {
|
|
return doris::TabletStorageType::STORAGE_TYPE_LOCAL;
|
|
} else if (local_reader == 0) {
|
|
return doris::TabletStorageType::STORAGE_TYPE_REMOTE;
|
|
}
|
|
return doris::TabletStorageType::STORAGE_TYPE_REMOTE_AND_LOCAL;
|
|
}
|
|
|
|
Status NewOlapScanner::_get_block_impl(RuntimeState* state, Block* block, bool* eof) {
|
|
// Read one block from block reader
|
|
// ATTN: Here we need to let the _get_block_impl method guarantee the semantics of the interface,
|
|
// that is, eof can be set to true only when the returned block is empty.
|
|
RETURN_IF_ERROR(_tablet_reader->next_block_with_aggregation(block, eof));
|
|
if (!_profile_updated) {
|
|
_profile_updated = _tablet_reader->update_profile(_profile);
|
|
}
|
|
if (block->rows() > 0) {
|
|
*eof = false;
|
|
}
|
|
_update_realtime_counters();
|
|
return Status::OK();
|
|
}
|
|
|
|
Status NewOlapScanner::close(RuntimeState* state) {
|
|
if (_is_closed) {
|
|
return Status::OK();
|
|
}
|
|
|
|
// olap scan node will call scanner.close() when finished
|
|
// will release resources here
|
|
// if not clear rowset readers in read_params here
|
|
// readers will be release when runtime state deconstructed but
|
|
// deconstructor in reader references runtime state
|
|
// so that it will core
|
|
_tablet_reader_params.rs_readers.clear();
|
|
_tablet_reader.reset();
|
|
|
|
RETURN_IF_ERROR(VScanner::close(state));
|
|
return Status::OK();
|
|
}
|
|
|
|
void NewOlapScanner::_update_realtime_counters() {
|
|
NewOlapScanNode* olap_parent = (NewOlapScanNode*)_parent;
|
|
auto& stats = _tablet_reader->stats();
|
|
COUNTER_UPDATE(olap_parent->_read_compressed_counter, stats.compressed_bytes_read);
|
|
_compressed_bytes_read += stats.compressed_bytes_read;
|
|
_tablet_reader->mutable_stats()->compressed_bytes_read = 0;
|
|
|
|
COUNTER_UPDATE(olap_parent->_raw_rows_counter, stats.raw_rows_read);
|
|
// if raw_rows_read is reset, scanNode will scan all table rows which may cause BE crash
|
|
_raw_rows_read += stats.raw_rows_read;
|
|
_tablet_reader->mutable_stats()->raw_rows_read = 0;
|
|
}
|
|
|
|
void NewOlapScanner::_update_counters_before_close() {
|
|
if (!_state->enable_profile() || _has_updated_counter) {
|
|
return;
|
|
}
|
|
_has_updated_counter = true;
|
|
|
|
VScanner::_update_counters_before_close();
|
|
|
|
// Update counters for NewOlapScanner
|
|
NewOlapScanNode* olap_parent = (NewOlapScanNode*)_parent;
|
|
|
|
// Update counters from tablet reader's stats
|
|
auto& stats = _tablet_reader->stats();
|
|
COUNTER_UPDATE(olap_parent->_io_timer, stats.io_ns);
|
|
COUNTER_UPDATE(olap_parent->_read_compressed_counter, stats.compressed_bytes_read);
|
|
_compressed_bytes_read += stats.compressed_bytes_read;
|
|
COUNTER_UPDATE(olap_parent->_decompressor_timer, stats.decompress_ns);
|
|
COUNTER_UPDATE(olap_parent->_read_uncompressed_counter, stats.uncompressed_bytes_read);
|
|
|
|
COUNTER_UPDATE(olap_parent->_block_load_timer, stats.block_load_ns);
|
|
COUNTER_UPDATE(olap_parent->_block_load_counter, stats.blocks_load);
|
|
COUNTER_UPDATE(olap_parent->_block_fetch_timer, stats.block_fetch_ns);
|
|
COUNTER_UPDATE(olap_parent->_block_convert_timer, stats.block_convert_ns);
|
|
|
|
COUNTER_UPDATE(olap_parent->_raw_rows_counter, stats.raw_rows_read);
|
|
// if raw_rows_read is reset, scanNode will scan all table rows which may cause BE crash
|
|
_raw_rows_read += _tablet_reader->mutable_stats()->raw_rows_read;
|
|
COUNTER_UPDATE(olap_parent->_vec_cond_timer, stats.vec_cond_ns);
|
|
COUNTER_UPDATE(olap_parent->_short_cond_timer, stats.short_cond_ns);
|
|
COUNTER_UPDATE(olap_parent->_expr_filter_timer, stats.expr_filter_ns);
|
|
COUNTER_UPDATE(olap_parent->_block_init_timer, stats.block_init_ns);
|
|
COUNTER_UPDATE(olap_parent->_block_init_seek_timer, stats.block_init_seek_ns);
|
|
COUNTER_UPDATE(olap_parent->_block_init_seek_counter, stats.block_init_seek_num);
|
|
COUNTER_UPDATE(olap_parent->_block_conditions_filtered_timer,
|
|
stats.block_conditions_filtered_ns);
|
|
COUNTER_UPDATE(olap_parent->_first_read_timer, stats.first_read_ns);
|
|
COUNTER_UPDATE(olap_parent->_second_read_timer, stats.second_read_ns);
|
|
COUNTER_UPDATE(olap_parent->_first_read_seek_timer, stats.block_first_read_seek_ns);
|
|
COUNTER_UPDATE(olap_parent->_first_read_seek_counter, stats.block_first_read_seek_num);
|
|
COUNTER_UPDATE(olap_parent->_lazy_read_timer, stats.lazy_read_ns);
|
|
COUNTER_UPDATE(olap_parent->_lazy_read_seek_timer, stats.block_lazy_read_seek_ns);
|
|
COUNTER_UPDATE(olap_parent->_lazy_read_seek_counter, stats.block_lazy_read_seek_num);
|
|
COUNTER_UPDATE(olap_parent->_output_col_timer, stats.output_col_ns);
|
|
COUNTER_UPDATE(olap_parent->_rows_vec_cond_filtered_counter, stats.rows_vec_cond_filtered);
|
|
COUNTER_UPDATE(olap_parent->_rows_short_circuit_cond_filtered_counter,
|
|
stats.rows_short_circuit_cond_filtered);
|
|
COUNTER_UPDATE(olap_parent->_rows_vec_cond_input_counter, stats.vec_cond_input_rows);
|
|
COUNTER_UPDATE(olap_parent->_rows_short_circuit_cond_input_counter,
|
|
stats.short_circuit_cond_input_rows);
|
|
|
|
for (auto& [id, info] : stats.filter_info) {
|
|
olap_parent->add_filter_info(id, info);
|
|
}
|
|
|
|
COUNTER_UPDATE(olap_parent->_stats_filtered_counter, stats.rows_stats_filtered);
|
|
COUNTER_UPDATE(olap_parent->_bf_filtered_counter, stats.rows_bf_filtered);
|
|
COUNTER_UPDATE(olap_parent->_del_filtered_counter, stats.rows_del_filtered);
|
|
COUNTER_UPDATE(olap_parent->_del_filtered_counter, stats.rows_del_by_bitmap);
|
|
COUNTER_UPDATE(olap_parent->_del_filtered_counter, stats.rows_vec_del_cond_filtered);
|
|
|
|
COUNTER_UPDATE(olap_parent->_conditions_filtered_counter, stats.rows_conditions_filtered);
|
|
COUNTER_UPDATE(olap_parent->_key_range_filtered_counter, stats.rows_key_range_filtered);
|
|
|
|
COUNTER_UPDATE(olap_parent->_total_pages_num_counter, stats.total_pages_num);
|
|
COUNTER_UPDATE(olap_parent->_cached_pages_num_counter, stats.cached_pages_num);
|
|
|
|
COUNTER_UPDATE(olap_parent->_bitmap_index_filter_counter, stats.rows_bitmap_index_filtered);
|
|
COUNTER_UPDATE(olap_parent->_bitmap_index_filter_timer, stats.bitmap_index_filter_timer);
|
|
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_filter_counter, stats.rows_inverted_index_filtered);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_filter_timer, stats.inverted_index_filter_timer);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_query_cache_hit_counter,
|
|
stats.inverted_index_query_cache_hit);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_query_cache_miss_counter,
|
|
stats.inverted_index_query_cache_miss);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_query_timer, stats.inverted_index_query_timer);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_query_bitmap_copy_timer,
|
|
stats.inverted_index_query_bitmap_copy_timer);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_query_bitmap_op_timer,
|
|
stats.inverted_index_query_bitmap_op_timer);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_searcher_open_timer,
|
|
stats.inverted_index_searcher_open_timer);
|
|
COUNTER_UPDATE(olap_parent->_inverted_index_searcher_search_timer,
|
|
stats.inverted_index_searcher_search_timer);
|
|
|
|
if (config::enable_file_cache) {
|
|
io::FileCacheProfileReporter cache_profile(olap_parent->_segment_profile.get());
|
|
cache_profile.update(&stats.file_cache_stats);
|
|
}
|
|
|
|
COUNTER_UPDATE(olap_parent->_output_index_result_column_timer,
|
|
stats.output_index_result_column_timer);
|
|
|
|
COUNTER_UPDATE(olap_parent->_filtered_segment_counter, stats.filtered_segment_number);
|
|
COUNTER_UPDATE(olap_parent->_total_segment_counter, stats.total_segment_number);
|
|
|
|
// Update metrics
|
|
DorisMetrics::instance()->query_scan_bytes->increment(_compressed_bytes_read);
|
|
DorisMetrics::instance()->query_scan_rows->increment(_raw_rows_read);
|
|
_tablet->query_scan_bytes->increment(_compressed_bytes_read);
|
|
_tablet->query_scan_rows->increment(_raw_rows_read);
|
|
_tablet->query_scan_count->increment(1);
|
|
}
|
|
|
|
} // namespace doris::vectorized
|