diff --git a/src/sql/rewrite/ob_transform_or_expansion.cpp b/src/sql/rewrite/ob_transform_or_expansion.cpp index 3dbca023e..846e11c7f 100644 --- a/src/sql/rewrite/ob_transform_or_expansion.cpp +++ b/src/sql/rewrite/ob_transform_or_expansion.cpp @@ -157,6 +157,7 @@ int ObTransformOrExpansion::transform_in_where_conditon(ObIArray &pa LOG_WARN("failed to check is valid semi anti cond", K(ret), K(*semi_info)); } else if (INVALID_OR_EXPAND_TYPE == ctx.or_expand_type_) { /*do nothing*/ - } else if (OB_FAIL(transform_or_expansion(spj_stmt, semi_info->semi_id_, i, - false, ctx, transformed_union_stmt, + } else if (OB_FAIL(transform_or_expansion(spj_stmt, + semi_info->semi_id_, + i, + ctx, + transformed_union_stmt, unique_key_provider))) { LOG_WARN("failed to do transformation", K(ret)); } else if (OB_FAIL(merge_stmt(trans_stmt, spj_stmt, transformed_union_stmt))) { @@ -431,9 +437,12 @@ int ObTransformOrExpansion::try_do_transform_inner_join(ObIArray if (reached_max_times_for_or_expansion()) { /*do nothing*/ OPT_TRACE("retry count reached max times:", try_times_); - } else if (OB_FAIL(transform_or_expansion(ref_query, joined_table->table_id_, - trans_infos.at(i).pos_, false, ctx, - trans_ref_query, unique_key_provider2))) { + } else if (OB_FAIL(transform_or_expansion(ref_query, + joined_table->table_id_, + trans_infos.at(i).pos_, + ctx, + trans_ref_query, + unique_key_provider2))) { LOG_WARN("failed to do transformation", K(ret)); } else if (OB_FAIL(do_transform_for_left_join(trans_ref_query, left_unique_pos, right_flag_pos))) { @@ -1438,6 +1450,7 @@ int ObTransformOrExpansion::get_common_columns_in_condition(const ObDMLStmt *stm LOG_WARN("failed to inner get same columns in condition", K(ret)); } for (int64_t i = 1; OB_SUCC(ret) && !pre_cols.empty() && i < expr->get_param_count(); ++i) { + cur_cols.reuse(); if (OB_FAIL(inner_get_common_columns_in_condition(stmt, expr->get_param_expr(i), cur_cols))) { LOG_WARN("failed to inner get same columns in condition", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::intersect(pre_cols, cur_cols, pre_cols))) { @@ -1812,6 +1825,7 @@ int ObTransformOrExpansion::is_valid_topk_cond(const ObDMLStmt &stmt, } else if (is_match) { trans_info.is_set_distinct_ = true; trans_info.or_expand_type_ |= OR_EXPAND_TOP_K; + trans_info.is_valid_topk_ = true; } } } @@ -1837,6 +1851,7 @@ int ObTransformOrExpansion::check_condition_valid_basic(const ObDMLStmt *stmt, is_valid = false; using_same_cols = true; common_cols.reuse(); + int classify_count = 0; OPT_TRACE("check expr:", expr); if (OB_ISNULL(stmt) || OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; @@ -1847,9 +1862,12 @@ int ObTransformOrExpansion::check_condition_valid_basic(const ObDMLStmt *stmt, } else if (T_OP_OR != expr->get_expr_type() && T_OP_IN != expr->get_expr_type()) { is_valid = false; OPT_TRACE("not or/in expr"); - } else if (T_OP_OR == expr->get_expr_type() && - expr->get_param_count() <= MAX_STMT_NUM_FOR_OR_EXPANSION) { - is_valid = expr->get_param_count() > 1; + } else if (T_OP_OR == expr->get_expr_type()) { + if (OB_FAIL(pre_classify_or_expr(expr, classify_count))) { + LOG_WARN("failed to classify or expr", K(ret)); + } else { + is_valid = expr->get_param_count() > 1 && classify_count <= MAX_STMT_NUM_FOR_OR_EXPANSION; + } } else if (is_topk && T_OP_IN == expr->get_expr_type() && !expr->has_flag(CNT_SUB_QUERY)) { const ObRawExpr *right_expr = NULL; if (OB_UNLIKELY(2 != expr->get_param_count())) { @@ -1888,6 +1906,10 @@ int ObTransformOrExpansion::check_condition_valid_basic(const ObDMLStmt *stmt, } else if (common_cols.empty() && using_same_cols && !expr->has_flag(CNT_SUB_QUERY)) { is_valid = false; OPT_TRACE("or expr from same table, will not expand"); + } else if (using_same_cols && T_OP_OR == expr->get_expr_type() + && expr->get_param_count() > MAX_STMT_NUM_FOR_OR_EXPANSION) { + is_valid = false; + OPT_TRACE("or expr param count > MAX_STMT_NUM_FOR_OR_EXPANSION, will not expand"); } else { is_valid = NULL == ctx.hint_ || ctx.hint_->enable_use_concat(*expr); if (!is_valid) { @@ -1933,6 +1955,10 @@ int ObTransformOrExpansion::is_condition_valid(const ObDMLStmt *stmt, OB_FAIL(is_valid_topk_cond(*stmt, expect_ordering, common_cols, equal_sets, const_exprs, trans_info))) { LOG_WARN("failed to check is valid topk cond", K(ret)); + } else if ((trans_info.or_expand_type_ & OR_EXPAND_TOP_K) + && T_OP_OR == expr->get_expr_type() + && expr->get_param_count() > MAX_STMT_NUM_FOR_OR_EXPANSION) { + trans_info.or_expand_type_ = INVALID_OR_EXPAND_TYPE; // means is_valid == false } else if (NULL != ctx.hint_ && ctx.hint_->is_enable_hint()) { // 2. match basic condition, do transform if use hint. if (OB_FAIL(get_use_hint_expand_type(*expr, can_set_distinct, trans_info))) { @@ -2071,7 +2097,6 @@ int ObTransformOrExpansion::is_expand_anti_or_cond(const ObRawExpr &expr, int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt, const uint64_t trans_id, const int64_t expr_pos, - bool is_topk, ObCostBasedRewriteCtx &ctx, ObSelectStmt *&trans_stmt, StmtUniqueKeyProvider &unique_key_provider) @@ -2111,7 +2136,7 @@ int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt, LOG_WARN("failed to get expand conds", K(ret)); } else if (FALSE_IT(view_stmt = copy_stmt)) { // never reach - } else if (OB_INVALID_ID == trans_id && !is_topk && + } else if (OB_INVALID_ID == trans_id && !ctx.is_valid_topk_ && OB_FAIL(get_condition_related_view(copy_stmt, view_stmt, view_table, view_expr_pos, conds_exprs, ctx.is_set_distinct_))) { @@ -2121,8 +2146,8 @@ int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt, } else if (ctx.is_set_distinct_ && !ctx.is_unique_ && OB_FAIL(unique_key_provider.recursive_set_stmt_unique(view_stmt, ctx_, true))) { LOG_WARN("failed to set stmt unique", K(ret)); - } else if (!is_topk && - OB_FAIL(classify_or_expr(*view_stmt, conds_exprs->at(view_expr_pos)))) { + } else if (!ctx.is_valid_topk_ + && OB_FAIL(classify_or_expr(*view_stmt, conds_exprs->at(view_expr_pos)))) { LOG_WARN("failed to classify or expr", K(ret), KPC(conds_exprs->at(view_expr_pos))); } else { const uint64_t or_expr_count = get_or_expr_count(*conds_exprs->at(view_expr_pos)); @@ -2415,6 +2440,7 @@ int ObTransformOrExpansion::is_valid_semi_anti_cond(const ObDMLStmt *stmt, int ret = OB_SUCCESS; trans_type = INVALID_OR_EXPAND_TYPE; bool check_status = false; + int classify_count = 0; OPT_TRACE("check expr:", expr); if (OB_ISNULL(stmt) || OB_ISNULL(expr) || OB_ISNULL(semi_info)) { ret = OB_ERR_UNEXPECTED; @@ -2422,9 +2448,7 @@ int ObTransformOrExpansion::is_valid_semi_anti_cond(const ObDMLStmt *stmt, } else if (expr->has_flag(CNT_ROWNUM)) { /* do nothing */ OPT_TRACE("expr has rownum"); - } else if (T_OP_OR != expr->get_expr_type() || - expr->get_param_count() <= 1 || - expr->get_param_count() > MAX_STMT_NUM_FOR_OR_EXPANSION) { + } else if (T_OP_OR != expr->get_expr_type() || expr->get_param_count() <= 1) { /* do nothing */ OPT_TRACE("not or expr"); } else if (OB_FAIL(check_condition_on_same_columns(*stmt, *expr, check_status))) { @@ -2432,6 +2456,11 @@ int ObTransformOrExpansion::is_valid_semi_anti_cond(const ObDMLStmt *stmt, } else if (check_status) { /* do nothing */ OPT_TRACE("or expr param from same table"); + } else if (OB_FAIL(pre_classify_or_expr(expr, classify_count))) { + LOG_WARN("failed to classify or expr", K(ret)); + } else if (classify_count > MAX_STMT_NUM_FOR_OR_EXPANSION) { + /* do nothing */ + OPT_TRACE("or expr classify count more than MAX_STMT_NUM_FOR_OR_EXPANSION"); } else if (NULL != ctx.hint_) { trans_type = ctx.hint_->enable_use_concat(*expr) ? OR_EXPAND_HINT : INVALID_OR_EXPAND_TYPE; if (INVALID_OR_EXPAND_TYPE == trans_type) { @@ -2441,7 +2470,7 @@ int ObTransformOrExpansion::is_valid_semi_anti_cond(const ObDMLStmt *stmt, LOG_WARN("failed to check is expand anti or cond", K(ret)); } else if (check_status) { /* do nothing */ - OPT_TRACE("is anti join or condition, do not exoand"); + OPT_TRACE("is anti join or condition, do not expand"); } else { const int64_t N = expr->get_param_count(); const ObRawExpr *child_expr = NULL; @@ -2879,6 +2908,53 @@ int ObTransformOrExpansion::construct_transform_hint(ObDMLStmt &stmt, void *tran return ret; } +// Classify or expr to get union count before do_transform +int ObTransformOrExpansion::pre_classify_or_expr(const ObRawExpr *expr, int &count) +{ + int ret = OB_SUCCESS; + ObSEArray table_col_bit_sets; + count = 0; + if (OB_ISNULL(expr) || T_OP_OR != expr->get_expr_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected expr", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { + TableColBitSet table_col_bit_set; + bool from_same_table = true; + int64_t table_id = OB_INVALID_ID; + const ObRawExpr *branch = NULL; + if (OB_ISNULL(branch = expr->get_param_expr(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (branch->has_flag(CNT_SUB_QUERY) || branch->get_relation_ids().is_empty()) { + // conditions with subqueries will be classfied separately + // irrelevant conditions will be classfied separately + ++count; + } else if (OB_FAIL(extract_columns(branch, + table_id, + from_same_table, + table_col_bit_set.column_bit_set_))) { + LOG_WARN("failed to extract columns info", K(ret), KPC(branch)); + } else if (!from_same_table) { + // conditions of multiple tables will be classfied separately + ++count; + } else if (OB_UNLIKELY(OB_INVALID_ID == table_id)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid table id", K(ret), KPC(branch), K(table_id)); + } else if (FALSE_IT(table_col_bit_set.table_id_ = table_id)) { + } else if (!ObOptimizerUtil::find_item(table_col_bit_sets, + table_col_bit_set)) { + if (OB_FAIL(table_col_bit_sets.push_back(table_col_bit_set))) { + LOG_WARN("failed to push back bit set", K(ret)); + } else { + ++count; + } + } + } + } + return ret; +} + // Classify isomorphic predicates into the same class // For example: // select * from t1,t2 where t1.a=1 or t1.a=t2.b or t1.a=t2.b+1 or t1.a>2 or t1.c=3 @@ -2948,9 +3024,8 @@ int ObTransformOrExpansion::classify_or_expr(const ObDMLStmt &stmt, ObRawExpr *& } if (OB_FAIL(ret) || !classify_happened) { - } else if (OB_UNLIKELY(1 == expr_classes.count())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("or expansion for same cols", K(ret)); + } else if (1 == expr_classes.count()) { + //do nothing } else { //modify the expr according to the partitions ObOpRawExpr *op_expr = static_cast(expr); diff --git a/src/sql/rewrite/ob_transform_or_expansion.h b/src/sql/rewrite/ob_transform_or_expansion.h index b3709a48c..652c94c71 100644 --- a/src/sql/rewrite/ob_transform_or_expansion.h +++ b/src/sql/rewrite/ob_transform_or_expansion.h @@ -66,6 +66,7 @@ class ObTransformOrExpansion: public ObTransformRule : trans_id_(OB_INVALID_ID), or_expand_type_(INVALID_OR_EXPAND_TYPE), is_set_distinct_(false), + is_valid_topk_(false), is_unique_(false), orig_expr_(NULL), hint_(NULL) {} @@ -75,6 +76,7 @@ class ObTransformOrExpansion: public ObTransformRule trans_id_ = OB_INVALID_ID; or_expand_type_ = INVALID_OR_EXPAND_TYPE; is_set_distinct_ = false; + is_valid_topk_ = false; is_unique_ = false; orig_expr_ = NULL; hint_ = NULL; @@ -82,6 +84,7 @@ class ObTransformOrExpansion: public ObTransformRule uint64_t trans_id_; uint64_t or_expand_type_; bool is_set_distinct_; // trans or expansion use distinct set + bool is_valid_topk_; // determine whether to do or classify when is_topk bool is_unique_; // spj stmt before trans is unique const ObRawExpr *orig_expr_; const ObOrExpandHint *hint_; @@ -92,13 +95,16 @@ class ObTransformOrExpansion: public ObTransformRule OrExpandInfo() : pos_(-1), or_expand_type_(INVALID_OR_EXPAND_TYPE), - is_set_distinct_(false) {} + is_set_distinct_(false), + is_valid_topk_(false) {} int64_t pos_; uint64_t or_expand_type_; bool is_set_distinct_; + bool is_valid_topk_; TO_STRING_KV(K_(pos), K_(or_expand_type), - K_(is_set_distinct)); + K_(is_set_distinct), + K_(is_valid_topk)); }; public: @@ -297,7 +303,6 @@ private: int transform_or_expansion(ObSelectStmt *stmt, const uint64_t trans_id, const int64_t expr_pos, - bool is_topk, ObCostBasedRewriteCtx &ctx, ObSelectStmt *&trans_stmt, StmtUniqueKeyProvider &unique_key_provider); @@ -361,6 +366,7 @@ private: int get_candi_match_index_exprs(ObRawExpr *expr, ObIArray &candi_exprs); + int pre_classify_or_expr(const ObRawExpr *expr, int &count); int classify_or_expr(const ObDMLStmt &stmt, ObRawExpr *&expr); int merge_expr_class(ObRawExpr *&expr_class, ObRawExpr *expr); int get_condition_related_tables(ObSelectStmt &stmt,