Change Null-safe equal operator from cross join to hash join (#2156)
* Change Null-safe equal operator from cross join to hash join ISSUE-2136 This commit change the join method from cross join to hash join when the equal operator is Null-safe '<=>'. It will improve the speed of query which has the Null-safe equal operator. The finds_nulls field is used to save if there is Null-safe operator. The finds_nulls[i] is true means that the i-th equal operator is Null-safe. The equal function in hash table will return true, if both val and loc are NULL when finds_nulls[i] is true.
This commit is contained in:
@ -71,6 +71,12 @@ Status HashJoinNode::init(const TPlanNode& tnode, RuntimeState* state) {
|
||||
_probe_expr_ctxs.push_back(ctx);
|
||||
RETURN_IF_ERROR(Expr::create_expr_tree(_pool, eq_join_conjuncts[i].right, &ctx));
|
||||
_build_expr_ctxs.push_back(ctx);
|
||||
if (eq_join_conjuncts[i].__isset.opcode
|
||||
&& eq_join_conjuncts[i].opcode == TExprOpcode::EQ_FOR_NULL) {
|
||||
_is_null_safe_eq_join.push_back(true);
|
||||
} else {
|
||||
_is_null_safe_eq_join.push_back(false);
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
@ -131,13 +137,13 @@ Status HashJoinNode::prepare(RuntimeState* state) {
|
||||
_build_tuple_row_size = num_build_tuples * sizeof(Tuple*);
|
||||
|
||||
// TODO: default buckets
|
||||
const bool stores_nulls = _join_op == TJoinOp::RIGHT_OUTER_JOIN
|
||||
const bool null_preserved = _join_op == TJoinOp::RIGHT_OUTER_JOIN
|
||||
|| _join_op == TJoinOp::FULL_OUTER_JOIN
|
||||
|| _join_op == TJoinOp::RIGHT_ANTI_JOIN
|
||||
|| _join_op == TJoinOp::RIGHT_SEMI_JOIN;
|
||||
_hash_tbl.reset(new HashTable(
|
||||
_build_expr_ctxs, _probe_expr_ctxs, _build_tuple_size,
|
||||
stores_nulls, id(), mem_tracker(), 1024));
|
||||
null_preserved, _is_null_safe_eq_join, id(), mem_tracker(), 1024));
|
||||
|
||||
_probe_batch.reset(new RowBatch(child(0)->row_desc(), state->batch_size(), mem_tracker()));
|
||||
|
||||
@ -286,6 +292,15 @@ Status HashJoinNode::open(RuntimeState* state) {
|
||||
_is_push_down = false;
|
||||
}
|
||||
|
||||
// The predicate could not be pushed down when there is Null-safe equal operator.
|
||||
// The in predicate will filter the null value in child[0] while it is needed in the Null-safe equal join.
|
||||
// For example: select * from a join b where a.id<=>b.id
|
||||
// the null value in table a should be return by scan node instead of filtering it by In-predicate.
|
||||
if (std::find(_is_null_safe_eq_join.begin(), _is_null_safe_eq_join.end(),
|
||||
true) != _is_null_safe_eq_join.end()) {
|
||||
_is_push_down = false;
|
||||
}
|
||||
|
||||
if (_is_push_down) {
|
||||
// Blocks until ConstructHashTable has returned, after which
|
||||
// the hash table is fully constructed and we can start the probe
|
||||
|
||||
Reference in New Issue
Block a user