You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2022/06/28 07:43:53 UTC
[doris] branch master updated: Revert "[improvement]Do not lazily read dict encoded columns (#10420)" (#10466)
This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7898c818e9 Revert "[improvement]Do not lazily read dict encoded columns (#10420)" (#10466)
7898c818e9 is described below
commit 7898c818e98a7546450976eac1892dec88af1f77
Author: Jerry Hu <mr...@gmail.com>
AuthorDate: Tue Jun 28 15:43:48 2022 +0800
Revert "[improvement]Do not lazily read dict encoded columns (#10420)" (#10466)
Reason:
1. Some queries performance degradation
2. Coredump bug: #10419
This reverts commit 904e7576797c796b809823647a769bc1d4569115.
---
be/src/olap/rowset/segment_v2/segment_iterator.cpp | 127 ++++++++++-----------
be/src/olap/rowset/segment_v2/segment_iterator.h | 8 +-
2 files changed, 64 insertions(+), 71 deletions(-)
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.cpp b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
index cc0e686131..61adede9f2 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.cpp
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
@@ -643,18 +643,13 @@ Status SegmentIterator::next_batch(RowBlockV2* block) {
// todo(wb) need a UT here
void SegmentIterator::_vec_init_lazy_materialization() {
- _is_first_read_column.resize(_schema.columns().size(), false);
+ _is_pred_column.resize(_schema.columns().size(), false);
// including short/vec/delete pred
std::set<ColumnId> pred_column_ids;
-
- // Other columns(not predicate columns) can read firstly together with predicate columns
- std::set<ColumnId> other_first_read_column_ids;
-
_lazy_materialization_read = false;
std::set<ColumnId> del_cond_id_set;
- std::set<ColumnId> lazy_read_column_ids;
_opts.delete_condition_predicates->get_all_column_ids(del_cond_id_set);
if (!_col_predicates.empty() || !del_cond_id_set.empty()) {
@@ -663,7 +658,7 @@ void SegmentIterator::_vec_init_lazy_materialization() {
for (auto predicate : _col_predicates) {
auto cid = predicate->column_id();
- _is_first_read_column[cid] = true;
+ _is_pred_column[cid] = true;
pred_column_ids.insert(cid);
// Step1: check pred using short eval or vec eval
@@ -686,7 +681,7 @@ void SegmentIterator::_vec_init_lazy_materialization() {
pred_column_ids.insert(del_cond_id_set.begin(), del_cond_id_set.end());
for (auto cid : del_cond_id_set) {
- _is_first_read_column[cid] = true;
+ _is_pred_column[cid] = true;
}
}
@@ -703,58 +698,65 @@ void SegmentIterator::_vec_init_lazy_materialization() {
}
// Step 2: check non-predicate read costs to determine whether need lazy materialization
+ // fill _non_predicate_columns.
// note(wb) For block schema, query layer and storage layer may have some diff
// query layer block schema not contains delete column, but storage layer appends delete column to end of block schema
// When output block to query layer, delete column can be skipped.
// _schema.column_ids() stands for storage layer block schema, so it contains delete columnid
// we just regard delete column as common pred column here.
- for (size_t i = 0; i < _schema.num_column_ids(); ++i) {
- auto cid = _schema.column_id(i);
- FieldType type = _schema.column(cid)->type();
- if (!_is_first_read_column[cid]) {
- switch (type) {
- case OLAP_FIELD_TYPE_VARCHAR:
- case OLAP_FIELD_TYPE_CHAR:
- case OLAP_FIELD_TYPE_STRING: {
- // if a string column is all dict encoding in one segment, it's almost same as
- // an int32_t column, it can be read together with predicate columns.
- if (config::enable_low_cardinality_optimize &&
- _column_iterators[cid]->is_all_dict_encoding()) {
- other_first_read_column_ids.insert(cid);
- _is_first_read_column[cid] = true;
- } else {
- lazy_read_column_ids.insert(cid);
+ if (_schema.column_ids().size() > pred_column_ids.size()) {
+ for (auto cid : _schema.column_ids()) {
+ if (!_is_pred_column[cid]) {
+ _non_predicate_columns.push_back(cid);
+ FieldType type = _schema.column(cid)->type();
+
+ // todo(wb) maybe we can make read char type faster
+ // todo(wb) support map/array type
+ // todo(wb) consider multiple integer columns cost, such as 1000 columns, maybe lazy materialization faster
+ if (!_lazy_materialization_read &&
+ (_is_need_vec_eval ||
+ _is_need_short_eval) && // only when pred exists, we need to consider lazy materialization
+ (type == OLAP_FIELD_TYPE_HLL || type == OLAP_FIELD_TYPE_OBJECT ||
+ type == OLAP_FIELD_TYPE_VARCHAR || type == OLAP_FIELD_TYPE_CHAR ||
+ type == OLAP_FIELD_TYPE_STRING || type == OLAP_FIELD_TYPE_BOOL ||
+ type == OLAP_FIELD_TYPE_DATE || type == OLAP_FIELD_TYPE_DATETIME ||
+ type == OLAP_FIELD_TYPE_DECIMAL)) {
+ _lazy_materialization_read = true;
}
- break;
- }
- case OLAP_FIELD_TYPE_HLL:
- case OLAP_FIELD_TYPE_OBJECT:
- case OLAP_FIELD_TYPE_BOOL:
- case OLAP_FIELD_TYPE_DATE:
- case OLAP_FIELD_TYPE_DATETIME:
- case OLAP_FIELD_TYPE_DECIMAL:
- lazy_read_column_ids.insert(cid);
- break;
- default:
- other_first_read_column_ids.insert(cid);
- _is_first_read_column[cid] = true;
- break;
}
}
}
- _first_read_column_ids.assign(pred_column_ids.begin(), pred_column_ids.end());
- _first_read_column_ids.insert(_first_read_column_ids.end(), other_first_read_column_ids.begin(),
- other_first_read_column_ids.end());
- if (_is_need_vec_eval || _is_need_short_eval) {
- _lazy_materialization_read = !lazy_read_column_ids.empty();
- _lazy_read_column_ids.assign(lazy_read_column_ids.begin(), lazy_read_column_ids.end());
- } else {
- _lazy_materialization_read = false;
-
- // No need to lazy read, all columns should be read firstly.
- _first_read_column_ids.insert(_first_read_column_ids.end(), lazy_read_column_ids.begin(),
- lazy_read_column_ids.end());
+ // Step 3: fill column ids for read and output
+ if (_lazy_materialization_read) {
+ // insert pred cid to first_read_columns
+ for (auto cid : pred_column_ids) {
+ _first_read_column_ids.push_back(cid);
+ }
+ } else if (!_is_need_vec_eval &&
+ !_is_need_short_eval) { // no pred exists, just read and output column
+ for (int i = 0; i < _schema.num_column_ids(); i++) {
+ auto cid = _schema.column_id(i);
+ _first_read_column_ids.push_back(cid);
+ }
+ } else { // pred exits, but we can eliminate lazy materialization
+ // insert pred/non-pred cid to first read columns
+ std::set<ColumnId> pred_id_set;
+ pred_id_set.insert(_short_cir_pred_column_ids.begin(), _short_cir_pred_column_ids.end());
+ pred_id_set.insert(_vec_pred_column_ids.begin(), _vec_pred_column_ids.end());
+ std::set<ColumnId> non_pred_set(_non_predicate_columns.begin(),
+ _non_predicate_columns.end());
+
+ for (int i = 0; i < _schema.num_column_ids(); i++) {
+ auto cid = _schema.column_id(i);
+ if (pred_id_set.find(cid) != pred_id_set.end()) {
+ _first_read_column_ids.push_back(cid);
+ } else if (non_pred_set.find(cid) != non_pred_set.end()) {
+ _first_read_column_ids.push_back(cid);
+ // when _lazy_materialization_read = false, non-predicate column should also be filtered by sel idx, so we regard it as pred columns
+ _is_pred_column[cid] = true;
+ }
+ }
}
// make _schema_block_id_map
@@ -820,7 +822,7 @@ void SegmentIterator::_init_current_block(
auto column_desc = _schema.column(cid);
// the column in block must clear() here to insert new data
- if (_is_first_read_column[cid] ||
+ if (_is_pred_column[cid] ||
i >= block->columns()) { //todo(wb) maybe we can release it after output block
current_columns[cid]->clear();
} else { // non-predicate column
@@ -839,14 +841,9 @@ void SegmentIterator::_init_current_block(
}
}
-void SegmentIterator::_output_lazy_read_columns(vectorized::Block* block) {
- _output_columns_by_relace(block, _lazy_read_column_ids);
-}
-
-void SegmentIterator::_output_columns_by_relace(vectorized::Block* block,
- const std::vector<ColumnId>& column_ids) {
+void SegmentIterator::_output_non_pred_columns(vectorized::Block* block) {
SCOPED_RAW_TIMER(&_opts.stats->output_col_ns);
- for (auto cid : column_ids) {
+ for (auto cid : _non_predicate_columns) {
auto loc = _schema_block_id_map[cid];
// if loc < block->block->columns() means the column is delete column and should
// not output by block, so just skip the column.
@@ -1007,7 +1004,7 @@ Status SegmentIterator::next_batch(vectorized::Block* block) {
for (size_t i = 0; i < _schema.num_column_ids(); i++) {
auto cid = _schema.column_id(i);
auto column_desc = _schema.column(cid);
- if (_is_first_read_column[cid]) {
+ if (_is_pred_column[cid]) {
_current_return_columns[cid] = Schema::get_predicate_column_nullable_ptr(
column_desc->type(), column_desc->is_nullable());
_current_return_columns[cid]->reserve(_opts.block_row_max);
@@ -1039,7 +1036,7 @@ Status SegmentIterator::next_batch(vectorized::Block* block) {
for (int i = 0; i < block->columns(); i++) {
auto cid = _schema.column_id(i);
// todo(wb) abstract make column where
- if (!_is_first_read_column[cid]) { // non-predicate
+ if (!_is_pred_column[cid]) { // non-predicate
block->replace_by_position(i, std::move(_current_return_columns[cid]));
}
}
@@ -1048,7 +1045,7 @@ Status SegmentIterator::next_batch(vectorized::Block* block) {
}
if (!_is_need_vec_eval && !_is_need_short_eval) {
- _output_columns_by_relace(block, _first_read_column_ids);
+ _output_non_pred_columns(block);
} else {
uint16_t selected_size = nrows_read;
uint16_t sel_rowid_idx[selected_size];
@@ -1073,13 +1070,13 @@ Status SegmentIterator::next_batch(vectorized::Block* block) {
return ret;
}
- // step3: read lazy_read_column_ids column
- _read_columns_by_rowids(_lazy_read_column_ids, _block_rowids, sel_rowid_idx, selected_size,
+ // step3: read non_predicate column
+ _read_columns_by_rowids(_non_predicate_columns, _block_rowids, sel_rowid_idx, selected_size,
&_current_return_columns);
// step4: output columns
- // 4.1 output lazy_read_column_ids column
- _output_lazy_read_columns(block);
+ // 4.1 output non-predicate column
+ _output_non_pred_columns(block);
// 4.3 output short circuit and predicate column
// when lazy materialization enables, _first_read_column_ids = distinct(_short_cir_pred_column_ids + _vec_pred_column_ids)
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.h b/be/src/olap/rowset/segment_v2/segment_iterator.h
index 541c721dc5..fbf44c34da 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.h
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.h
@@ -101,9 +101,7 @@ private:
std::vector<vectorized::MutableColumnPtr>& non_pred_vector);
uint16_t _evaluate_vectorization_predicate(uint16_t* sel_rowid_idx, uint16_t selected_size);
uint16_t _evaluate_short_circuit_predicate(uint16_t* sel_rowid_idx, uint16_t selected_size);
- void _output_lazy_read_columns(vectorized::Block* block);
- void _output_columns_by_relace(vectorized::Block* block,
- const std::vector<ColumnId>& column_ids);
+ void _output_non_pred_columns(vectorized::Block* block);
void _read_columns_by_rowids(std::vector<ColumnId>& read_column_ids,
std::vector<rowid_t>& rowid_vector, uint16_t* sel_rowid_idx,
size_t select_size, vectorized::MutableColumns* mutable_columns);
@@ -158,7 +156,7 @@ private:
_vec_pred_column_ids; // keep columnId of columns for vectorized predicate evaluation
std::vector<ColumnId>
_short_cir_pred_column_ids; // keep columnId of columns for short circuit predicate evaluation
- std::vector<bool> _is_first_read_column; // columns hold by segmentIter
+ std::vector<bool> _is_pred_column; // columns hold by segmentIter
vectorized::MutableColumns _current_return_columns;
std::unique_ptr<AndBlockColumnPredicate> _pre_eval_block_predicate;
std::vector<ColumnPredicate*> _short_cir_eval_predicate;
@@ -167,8 +165,6 @@ private:
// second, read non-predicate columns
// so we need a field to stand for columns first time to read
std::vector<ColumnId> _first_read_column_ids;
- std::vector<ColumnId> _lazy_read_column_ids;
-
std::vector<int> _schema_block_id_map; // map from schema column id to column idx in Block
// the actual init process is delayed to the first call to next_batch()
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org