Fix null aware anti join bug

This commit is contained in:
xianyu-w 2023-05-16 10:11:20 +00:00 committed by ob-robot
parent b5ac0c7bf6
commit 11437edf50
4 changed files with 119 additions and 63 deletions

View File

@ -7635,6 +7635,7 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
other_cond_sel,
get_plan()->get_predicate_selectivities()))) {
LOG_WARN("failed to calculate selectivity", K(ret), K(hash_join_filters));
} else if (FALSE_IT(naaj_info.set_is_sna(path_info.join_type_, false))) {
} else if ((HASH_JOIN & path_info.local_methods_) &&
OB_FAIL(generate_hash_paths(equal_sets,
left_paths,
@ -7648,9 +7649,9 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
equal_cond_sel,
other_cond_sel,
path_info,
naaj_info.is_naaj_,
naaj_info.get_is_sna(path_info.join_type_, false)))) {
naaj_info))) {
LOG_WARN("failed to generate hash join paths", K(ret));
} else if (FALSE_IT(naaj_info.set_is_sna(reverse_path_info.join_type_, true))) {
} else if ((HASH_JOIN & reverse_path_info.local_methods_) &&
OB_FAIL(generate_hash_paths(equal_sets,
right_paths,
@ -7664,8 +7665,7 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
equal_cond_sel,
other_cond_sel,
reverse_path_info,
naaj_info.is_naaj_,
naaj_info.get_is_sna(reverse_path_info.join_type_, true)))) {
naaj_info))) {
LOG_WARN("failed to generate hash join paths", K(ret));
} else {
int64_t hash_join_path_num = interesting_paths_.count() - path_number;
@ -7819,8 +7819,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
const double equal_cond_sel,
const double other_cond_sel,
const ValidPathInfo &path_info,
const bool is_naaj,
const bool is_sna)
const NullAwareAntiJoinInfo &naaj_info)
{
int ret = OB_SUCCESS;
ObSEArray<Path*, 8> left_best_paths;
@ -7852,7 +7851,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
path_info,
HASH_JOIN,
false,
is_naaj,
naaj_info.is_naaj_,
dist_method))) {
LOG_WARN("failed to get distributed join method", K(ret));
} else {
@ -7874,8 +7873,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
join_quals,
equal_cond_sel,
other_cond_sel,
is_naaj,
is_sna))) {
naaj_info))) {
LOG_WARN("failed to create and add hash path", K(ret));
} else { /*do nothing*/ }
}
@ -9110,8 +9108,7 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
const ObIArray<ObRawExpr*> &filters,
const double equal_cond_sel,
const double other_cond_sel,
const bool is_naaj,
const bool is_sna)
const NullAwareAntiJoinInfo &naaj_info)
{
int ret = OB_SUCCESS;
JoinPath *join_path = NULL;
@ -9137,9 +9134,9 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
join_type);
join_path->equal_cond_sel_ = equal_cond_sel;
join_path->other_cond_sel_ = other_cond_sel;
join_path->is_naaj_ = is_naaj;
join_path->is_sna_ = is_sna;
join_path->is_slave_mapping_ &= (!is_naaj);
join_path->is_naaj_ = naaj_info.is_naaj_;
join_path->is_sna_ = naaj_info.is_sna_;
join_path->is_slave_mapping_ &= (!naaj_info.is_naaj_);
OPT_TRACE("create new Hash Join path:", join_path);
if (OB_FAIL(append(join_path->equal_join_conditions_, equal_join_conditions))) {
LOG_WARN("failed to append join conditions", K(ret));
@ -9147,12 +9144,14 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
LOG_WARN("failed to append join filters", K(ret));
} else if (OB_FAIL(append(join_path->filter_, normal_filters))) {
LOG_WARN("failed to append join quals", K(ret));
} else if (OB_FAIL(append(join_path->expr_constraints_, naaj_info.expr_constraints_))) {
LOG_WARN("failed to append constraints", K(ret));
} else if (OB_FAIL(generate_join_filter_infos(*left_path,
*right_path,
join_type,
join_dist_algo,
equal_join_conditions,
is_naaj,
naaj_info.is_naaj_,
join_path->join_filter_infos_))) {
LOG_WARN("failed to generate join filter info", K(ret));
} else if (OB_FAIL(join_path->compute_join_path_property())) {
@ -9922,8 +9921,7 @@ int ObJoinOrder::extract_hashjoin_conditions(const ObIArray<ObRawExpr*> &join_qu
LOG_WARN("failed to get sys var naaj enabled", K(ret));
} else if (naaj_enabled) {
if (OB_FAIL(extract_naaj_join_conditions(join_quals, left_tables, right_tables,
equal_join_conditions, other_join_conditions,
naaj_info))) {
equal_join_conditions, naaj_info))) {
LOG_WARN("failed to extract naaj join conditions", K(ret));
}
}
@ -13716,7 +13714,6 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
const ObRelIds &left_tables,
const ObRelIds &right_tables,
ObIArray<ObRawExpr*> &equal_join_conditions,
ObIArray<ObRawExpr*> &other_join_conditions,
NullAwareAntiJoinInfo &naaj_info)
{
int ret = OB_SUCCESS;
@ -13731,17 +13728,18 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
} else if (T_OP_OR == join_quals.at(0)->get_expr_type()) {
for (int64_t i = 0; OB_SUCC(ret) && i < join_quals.at(0)->get_param_count(); ++i) {
bool is_equal_cond = false;
bool skip_left = false;
bool skip_right = false;
cur_expr = join_quals.at(0)->get_param_expr(i);
if (OB_FAIL(check_is_join_equal_conditions(cur_expr, left_tables,
right_tables, is_equal_cond))) {
LOG_WARN("failed to check equal cond", K(cur_expr), K(ret));
} else if (is_equal_cond) {
OZ (join_quals_naaj.push_back(cur_expr));
if (OB_FAIL(join_quals_naaj.push_back(cur_expr))) {
LOG_WARN("failed to push back", K(ret));
}
} else {
if (cur_expr->get_relation_ids().is_subset(get_tables())) {
OZ (join_other_naaj.push_back(cur_expr));
if (cur_expr->get_relation_ids().is_subset(get_tables()) &&
OB_FAIL(join_other_naaj.push_back(cur_expr))) {
LOG_WARN("failed to push back", K(ret));
}
}
}
@ -13752,33 +13750,68 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
left_join_key = join_quals_naaj.at(0)->get_param_expr(1);
right_join_key = join_quals_naaj.at(0)->get_param_expr(0);
}
bool left_is_null_eliminate = true;
bool right_is_null_eliminate = true;
for (int64_t i = 0; OB_SUCC(ret) && i < join_other_naaj.count(); ++i) {
bool left_has_is_null = false;
bool right_has_is_null = false;
bool is_valid = true;
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < join_other_naaj.count(); ++i) {
//eliminate join_key is null
cur_expr = join_other_naaj.at(i);
if (T_OP_IS == cur_expr->get_expr_type()
&& ObNullType == cur_expr->get_param_expr(1)->get_result_type().get_type()) {
if (left_join_key == cur_expr->get_param_expr(0)) {
left_is_null_eliminate = false;
left_has_is_null = true;
} else if (right_join_key == cur_expr->get_param_expr(0)) {
right_is_null_eliminate = false;
right_has_is_null = true;
} else {
OZ (other_join_conditions.push_back(join_other_naaj.at(i)));
is_valid = false;
}
} else {
is_valid = false;
}
}
if (OB_FAIL(ret) || !is_valid) {
// do nothing
} else if (left_has_is_null && right_has_is_null) {
// Both "is null" was eliminated
// anti join na
// e.g. (a = b) or (a is null) or (b is null)
naaj_info.is_naaj_ = true;
if (OB_FAIL(equal_join_conditions.push_back(join_quals_naaj.at(0)))) {
LOG_WARN("failed to push back", K(ret));
}
} else if (left_has_is_null || right_has_is_null) {
// Only one "is null" was eliminated,
// Other side should be not null
// e.g. ((a = b) or (a is null)) and (b is not null)
// <=> ((a = b) or (a is null) or (b is null)) and (b is not null)
ObNotNullContext not_null_ctx(get_plan()->get_optimizer_context().get_exec_ctx(),
&get_plan()->get_allocator(),
get_plan()->get_stmt());
ObArray<ObRawExpr *> constraints;
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_WHERE))) {
LOG_WARN("failed to generate stmt context", K(ret));
} else if (OB_FAIL(not_null_ctx.remove_filter(join_quals.at(0)))){
LOG_WARN("failed to remove filter", K(ret));
} else if (!left_has_is_null &&
OB_FAIL(ObTransformUtils::is_expr_not_null(not_null_ctx, left_join_key,
naaj_info.left_side_not_null_, &constraints))) {
LOG_WARN("failed to check is expr not null");
} else if (!right_has_is_null &&
OB_FAIL(ObTransformUtils::is_expr_not_null(not_null_ctx, right_join_key,
naaj_info.right_side_not_null_, &constraints))) {
LOG_WARN("failed to check is expr not null");
} else if (OB_FAIL(ObTransformUtils::add_param_not_null_constraint(naaj_info.expr_constraints_, constraints))) {
LOG_WARN("append expr constraints failed", K(ret));
} else if (naaj_info.left_side_not_null_ || naaj_info.right_side_not_null_) {
naaj_info.is_naaj_ = true;
if (OB_FAIL(equal_join_conditions.push_back(join_quals_naaj.at(0)))) {
LOG_WARN("failed to push back", K(ret));
}
}
}
// at least 1 isnull cond to choose naaj
if (!left_is_null_eliminate || !right_is_null_eliminate) {
naaj_info.is_naaj_ = true;
naaj_info.left_side_not_null_ = left_is_null_eliminate;
naaj_info.right_side_not_null_ = right_is_null_eliminate;
OZ (equal_join_conditions.push_back(join_quals_naaj.at(0)));
} else {
//rollback for other_join_conditions
other_join_conditions.reset();
}
}
LOG_TRACE("extract naaj info", K(naaj_info), K(equal_join_conditions));
}
return ret;
}

View File

@ -1195,25 +1195,28 @@ struct InnerPathInfo {
typedef common::ObSEArray<InnerPathInfo, 8, common::ModulePageAllocator, true> InnerPathInfos;
struct NullAwareAntiJoinInfo {
NullAwareAntiJoinInfo() : is_naaj_(false),
NullAwareAntiJoinInfo() : is_naaj_(false), is_sna_(false),
left_side_not_null_(false), right_side_not_null_(false) {}
~NullAwareAntiJoinInfo() {}
TO_STRING_KV(K_(is_naaj), K_(left_side_not_null), K_(right_side_not_null));
bool get_is_sna(const ObJoinType &join_type, const bool is_reverse_path) const
TO_STRING_KV(K_(is_naaj), K_(is_sna), K_(left_side_not_null), K_(right_side_not_null), K_(expr_constraints));
void set_is_sna(const ObJoinType &join_type, const bool is_reverse_path)
{
bool is_sna = false;
if (is_reverse_path) {
is_sna = ((LEFT_ANTI_JOIN == join_type && left_side_not_null_)
|| (RIGHT_ANTI_JOIN == join_type && right_side_not_null_));
} else {
is_sna = ((LEFT_ANTI_JOIN == join_type && right_side_not_null_)
|| (RIGHT_ANTI_JOIN == join_type && left_side_not_null_));
if (is_naaj_) {
if (is_reverse_path) {
is_sna_ = ((LEFT_ANTI_JOIN == join_type && left_side_not_null_)
|| (RIGHT_ANTI_JOIN == join_type && right_side_not_null_));
} else {
is_sna_ = ((LEFT_ANTI_JOIN == join_type && right_side_not_null_)
|| (RIGHT_ANTI_JOIN == join_type && left_side_not_null_));
}
}
return is_sna;
return;
}
bool is_naaj_;
bool is_sna_;
bool left_side_not_null_;
bool right_side_not_null_;
ObSEArray<ObExprConstraint, 2> expr_constraints_;
};
class ObJoinOrder
@ -1807,8 +1810,7 @@ struct NullAwareAntiJoinInfo {
const double equal_cond_sel,
const double other_cond_sel,
const ValidPathInfo &path_info,
const bool is_naaj,
const bool is_sna);
const NullAwareAntiJoinInfo &naaj_info);
int generate_mj_paths(const EqualSets &equal_sets,
const ObIArray<ObSEArray<Path*, 16>> &left_paths,
@ -1884,8 +1886,7 @@ struct NullAwareAntiJoinInfo {
const common::ObIArray<ObRawExpr*> &filters,
const double equal_cond_sel,
const double other_cond_sel,
const bool is_naaj,
const bool is_sna);
const NullAwareAntiJoinInfo &naaj_info);
int generate_join_filter_infos(const Path &left_path,
const Path &right_path,
@ -2440,7 +2441,6 @@ struct NullAwareAntiJoinInfo {
const ObRelIds &left_tables,
const ObRelIds &right_tables,
ObIArray<ObRawExpr*> &equal_join_conditions,
ObIArray<ObRawExpr*> &other_join_conditions,
NullAwareAntiJoinInfo &naaj_info);
bool is_main_table_use_das(const common::ObIArray<AccessPath *> &access_paths);
int add_deduced_expr(ObRawExpr *deduced_expr, ObRawExpr *deduce_from, bool is_persistent);

View File

@ -9518,20 +9518,19 @@ int ObTransformUtils::extract_shared_expr(ObDMLStmt *upper_stmt,
return ret;
}
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
int ObTransformUtils::add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
ObIArray<ObRawExpr *> &not_null_exprs)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < not_null_exprs.count(); ++i) {
if (OB_FAIL(add_param_not_null_constraint(ctx, not_null_exprs.at(i)))) {
if (OB_FAIL(add_param_not_null_constraint(constraints, not_null_exprs.at(i)))) {
LOG_WARN("failed to add param not null constraint", K(ret));
}
}
return ret;
}
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
int ObTransformUtils::add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
ObRawExpr *not_null_expr,
bool is_true)
{
@ -9544,16 +9543,16 @@ int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("pre calculable expr is expected here", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < ctx.expr_constraints_.count(); ++i) {
if (ctx.expr_constraints_.at(i).expect_result_ == PRE_CALC_RESULT_NOT_NULL &&
ctx.expr_constraints_.at(i).pre_calc_expr_ == not_null_expr) {
for (int64_t i = 0; OB_SUCC(ret) && i < constraints.count(); ++i) {
if (constraints.at(i).expect_result_ == PRE_CALC_RESULT_NOT_NULL &&
constraints.at(i).pre_calc_expr_ == not_null_expr) {
existed = true;
break;
}
}
if (OB_SUCC(ret) && !existed) {
ObExprConstraint cons(not_null_expr, PRE_CALC_RESULT_NOT_NULL);
if (OB_FAIL(ctx.expr_constraints_.push_back(cons))) {
if (OB_FAIL(constraints.push_back(cons))) {
LOG_WARN("failed to push back pre calc constraints", K(ret));
}
}
@ -9561,6 +9560,23 @@ int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
return ret;
}
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
ObIArray<ObRawExpr *> &not_null_exprs)
{
int ret = OB_SUCCESS;
ret = add_param_not_null_constraint(ctx.expr_constraints_, not_null_exprs);
return ret;
}
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
ObRawExpr *not_null_expr,
bool is_true)
{
int ret = OB_SUCCESS;
ret = add_param_not_null_constraint(ctx.expr_constraints_, not_null_expr, is_true);
return ret;
}
int ObTransformUtils::add_param_null_constraint(ObTransformerCtx &ctx,
ObRawExpr *null_expr)
{

View File

@ -1434,6 +1434,13 @@ public:
bool in_add_expr);
static int add_constraint_for_groupby_expr(ObTransformerCtx *trans_ctx, ObSelectStmt *select_stmt, ObRawExpr* groupby_expr, ObRawExpr* old_expr);
static int add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
ObIArray<ObRawExpr *> &not_null_exprs);
static int add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
ObRawExpr *not_null_expr,
bool is_true = true);
static int add_param_not_null_constraint(ObTransformerCtx &ctx,
ObIArray<ObRawExpr *> &not_null_exprs);