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 c18a471303 [Optimize](predicate) update inplace on VcompoundPred
(#14402)
c18a471303 is described below
commit c18a4713036994b7c5b436ab037d5b691bdc2607
Author: Pxl <[email protected]>
AuthorDate: Mon Nov 21 09:12:30 2022 +0800
[Optimize](predicate) update inplace on VcompoundPred (#14402)
select count(*) from lineorder where lo_orderkey<100000000 OR
lo_orderkey>100000000 AND lo_orderkey<200000000 OR lo_orderkey >200000000;
0.6s -> 0.5s
---
.clang-tidy | 8 +-
be/src/vec/exprs/vcompound_pred.h | 166 ++++++++++++++++++++++++++++----
be/src/vec/exprs/vectorized_fn_call.cpp | 2 +-
be/src/vec/exprs/vectorized_fn_call.h | 24 ++---
be/src/vec/exprs/vexpr.h | 2 +
5 files changed, 166 insertions(+), 36 deletions(-)
diff --git a/.clang-tidy b/.clang-tidy
index 7b4a2a53a0..62295d27b9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -3,19 +3,19 @@ Checks: |
clang-diagnostic-*,
clang-analyzer-*,
-*,
+ bugprone-redundant-branch-condition,
modernize-use-override,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nullptr,
modernize-use-bool-literals,
modernize-use-using,
+ misc-redundant-expression,
+ misc-unused-*,
readability-make-member-function-const,
readability-non-const-parameter,
readability-static-accessed-through-instance,
- readability-redundant-smartptr-get,
- readability-redundant-member-init,
- readability-redundant-string-cstr,
- readability-redundant-string-init,
+ readability-redundant-*,
readability-braces-around-statements,
portability-simd-intrinsics,
performance-type-promotion-in-math-fn,
diff --git a/be/src/vec/exprs/vcompound_pred.h
b/be/src/vec/exprs/vcompound_pred.h
index 5d3e6be25c..156c10ce54 100644
--- a/be/src/vec/exprs/vcompound_pred.h
+++ b/be/src/vec/exprs/vcompound_pred.h
@@ -16,38 +16,170 @@
// under the License.
#pragma once
-#include "runtime/runtime_state.h"
+#include <gen_cpp/Opcodes_types.h>
+
+#include "common/status.h"
+#include "util/simd/bits.h"
+#include "vec/columns/column.h"
+#include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
#include "vec/exprs/vectorized_fn_call.h"
#include "vec/exprs/vexpr.h"
-#include "vec/functions/function.h"
namespace doris::vectorized {
-class VcompoundPred final : public VectorizedFnCall {
+inline std::string compound_operator_to_string(TExprOpcode::type op) {
+ if (op == TExprOpcode::COMPOUND_AND) {
+ return "and";
+ } else if (op == TExprOpcode::COMPOUND_OR) {
+ return "or";
+ } else {
+ return "not";
+ }
+}
+
+class VcompoundPred : public VectorizedFnCall {
public:
VcompoundPred(const TExprNode& node) : VectorizedFnCall(node) {
- switch (node.opcode) {
- case TExprOpcode::COMPOUND_AND:
- _fn.name.function_name = "and";
- break;
- case TExprOpcode::COMPOUND_OR:
- _fn.name.function_name = "or";
- break;
- default:
- _fn.name.function_name = "not";
- break;
+ _op = node.opcode;
+ _fn.name.function_name = compound_operator_to_string(_op);
+ _expr_name = "CompoundPredicate (" + _fn.name.function_name + ")";
+ }
+
+ VExpr* clone(ObjectPool* pool) const override { return pool->add(new
VcompoundPred(*this)); }
+
+ const std::string& expr_name() const override { return _expr_name; }
+
+ Status execute(VExprContext* context, doris::vectorized::Block* block,
+ int* result_column_id) override {
+ if (children().size() == 1 || !_all_child_is_compound_and_not_const())
{
+ return VectorizedFnCall::execute(context, block, result_column_id);
+ }
+
+ int lhs_id = -1;
+ int rhs_id = -1;
+ RETURN_IF_ERROR(_children[0]->execute(context, block, &lhs_id));
+ ColumnPtr lhs_column = block->get_by_position(lhs_id).column;
+
+ ColumnPtr rhs_column = nullptr;
+
+ size_t size = lhs_column->size();
+ uint8* __restrict data = _get_raw_data(lhs_column);
+ int filted = simd::count_zero_num((int8_t*)data, size);
+ bool full = filted == 0;
+ bool empty = filted == size;
+
+ const uint8* __restrict data_rhs = nullptr;
+ bool full_rhs = false;
+ bool empty_rhs = false;
+
+ auto get_rhs_colum = [&]() {
+ if (rhs_id == -1) {
+ RETURN_IF_ERROR(_children[1]->execute(context, block,
&rhs_id));
+ rhs_column = block->get_by_position(rhs_id).column;
+ data_rhs = _get_raw_data(rhs_column);
+ if (!empty) {
+ if (const uint8* null_map =
+
_get_null_map(block->get_by_position(rhs_id).column);
+ null_map != nullptr) {
+ for (size_t i = 0; i < size; i++) {
+ data[i] &= !null_map[i];
+ }
+ }
+ }
+ int filted = simd::count_zero_num((int8_t*)data_rhs, size);
+ full_rhs = filted == 0;
+ empty_rhs = filted == size;
+ }
+ return Status::OK();
+ };
+
+ if (_op == TExprOpcode::COMPOUND_AND) {
+ if (!empty) { // empty and any = empty, so lhs should not empty
+ RETURN_IF_ERROR(get_rhs_colum());
+ if (empty_rhs) { // any and empty = empty
+ *result_column_id = rhs_id;
+ return Status::OK();
+ } else if (!full_rhs) { // any and full = any, so rhs should
not full.
+ for (size_t i = 0; i < size; i++) {
+ data[i] &= data_rhs[i];
+ }
+ }
+ }
+ } else if (_op == TExprOpcode::COMPOUND_OR) {
+ if (!full) { // full or any = full, so lhs should not full
+ RETURN_IF_ERROR(get_rhs_colum());
+ if (full_rhs) { // any or full = full
+ *result_column_id = rhs_id;
+ return Status::OK();
+ } else if (!empty_rhs) { // any or empty = any, so rhs should
not empty
+ for (size_t i = 0; i < size; i++) {
+ data[i] |= data_rhs[i];
+ }
+ }
+ }
+ } else {
+ LOG(FATAL) << "Compound operator must be AND or OR.";
}
+
+ *result_column_id = lhs_id;
+ return Status::OK();
}
std::string debug_string() const override {
std::stringstream out;
- out << "CompoundPredicate {" << _fn.name.function_name;
- out << " (" << _children[0]->debug_string();
+ out << _expr_name << "{\n";
+ out << _children[0]->debug_string();
if (children().size() > 1) {
- out << ", " << _children[1]->debug_string();
+ out << ",\n" << _children[1]->debug_string();
}
- out << ")}";
+ out << "}";
return out.str();
}
+
+ bool is_compound_predicate() const override { return true; }
+
+private:
+ bool _all_child_is_compound_and_not_const() const {
+ for (auto child : _children) {
+ // we can make sure non const compound predicate's return column
is allow modifyied locally.
+ if (child->is_constant() || !child->is_compound_predicate()) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ uint8* _get_raw_data(ColumnPtr column) const {
+ if (column->is_nullable()) {
+ return reinterpret_cast<ColumnUInt8*>(
+
assert_cast<ColumnNullable*>(column->assume_mutable().get())
+ ->get_nested_column_ptr()
+ .get())
+ ->get_data()
+ .data();
+ } else {
+ return
reinterpret_cast<ColumnUInt8*>(column->assume_mutable().get())
+ ->get_data()
+ .data();
+ }
+ }
+
+ uint8* _get_null_map(ColumnPtr column) const {
+ if (column->is_nullable()) {
+ return reinterpret_cast<ColumnUInt8*>(
+
reinterpret_cast<ColumnNullable*>(column->assume_mutable().get())
+ ->get_null_map_column_ptr()
+ .get())
+ ->get_data()
+ .data();
+ } else {
+ return nullptr;
+ }
+ }
+
+ TExprOpcode::type _op;
+
+ std::string _expr_name;
};
} // namespace doris::vectorized
diff --git a/be/src/vec/exprs/vectorized_fn_call.cpp
b/be/src/vec/exprs/vectorized_fn_call.cpp
index c535ca266f..3999599716 100644
--- a/be/src/vec/exprs/vectorized_fn_call.cpp
+++ b/be/src/vec/exprs/vectorized_fn_call.cpp
@@ -126,7 +126,7 @@ std::string VectorizedFnCall::debug_string() const {
} else {
out << ",";
}
- out << input_expr->debug_string();
+ out << "\n" << input_expr->debug_string();
}
out << "}";
return out.str();
diff --git a/be/src/vec/exprs/vectorized_fn_call.h
b/be/src/vec/exprs/vectorized_fn_call.h
index cdd3ef211e..63a11847db 100644
--- a/be/src/vec/exprs/vectorized_fn_call.h
+++ b/be/src/vec/exprs/vectorized_fn_call.h
@@ -23,20 +23,16 @@
namespace doris::vectorized {
class VectorizedFnCall : public VExpr {
public:
- VectorizedFnCall(const doris::TExprNode& node);
- virtual doris::Status execute(VExprContext* context,
doris::vectorized::Block* block,
- int* result_column_id) override;
- virtual doris::Status prepare(doris::RuntimeState* state, const
doris::RowDescriptor& desc,
- VExprContext* context) override;
- virtual doris::Status open(doris::RuntimeState* state, VExprContext*
context,
- FunctionContext::FunctionStateScope scope)
override;
- virtual void close(doris::RuntimeState* state, VExprContext* context,
- FunctionContext::FunctionStateScope scope) override;
- virtual VExpr* clone(doris::ObjectPool* pool) const override {
- return pool->add(new VectorizedFnCall(*this));
- }
- virtual const std::string& expr_name() const override;
- virtual std::string debug_string() const override;
+ VectorizedFnCall(const TExprNode& node);
+ Status execute(VExprContext* context, Block* block, int* result_column_id)
override;
+ Status prepare(RuntimeState* state, const RowDescriptor& desc,
VExprContext* context) override;
+ Status open(RuntimeState* state, VExprContext* context,
+ FunctionContext::FunctionStateScope scope) override;
+ void close(RuntimeState* state, VExprContext* context,
+ FunctionContext::FunctionStateScope scope) override;
+ VExpr* clone(ObjectPool* pool) const override { return pool->add(new
VectorizedFnCall(*this)); }
+ const std::string& expr_name() const override;
+ std::string debug_string() const override;
static std::string debug_string(const std::vector<VectorizedFnCall*>&
exprs);
private:
diff --git a/be/src/vec/exprs/vexpr.h b/be/src/vec/exprs/vexpr.h
index 35b78635ab..beefec98e0 100644
--- a/be/src/vec/exprs/vexpr.h
+++ b/be/src/vec/exprs/vexpr.h
@@ -134,6 +134,8 @@ public:
bool is_and_expr() const { return _fn.name.function_name == "and"; }
+ virtual bool is_compound_predicate() const { return false; }
+
const TFunction& fn() const { return _fn; }
/// Returns true if expr doesn't contain slotrefs, i.e., can be evaluated
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]