diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index a98ef9a2e7..e4859400bc 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -7424,6 +7424,55 @@ int ObJoinOrder::generate_temp_table_paths() return ret; } +int ObJoinOrder::extract_necessary_pushdown_quals(ObIArray &candi_quals, + ObIArray &necessary_pushdown_quals, + ObIArray &unnecessary_pushdown_quals) +{ + int ret = OB_SUCCESS; + const ObDMLStmt *stmt = NULL; + if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(get_plan()), K(stmt)); + } else if (stmt->is_hierarchical_query()) { + /** + * PredicateMoveAround skipped hierarchical query, + * so we push down all of its quals here. + */ + if (OB_FAIL(append(necessary_pushdown_quals, candi_quals))) { + LOG_WARN("failed to append", K(ret)); + } + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < candi_quals.count(); i ++) { + ObRawExpr *expr = candi_quals.at(i); + /** + * Only push down such filters here: + * a. Filters contain dynamic param, such as onetime exprs: `a = ?` + * select * from (select * from t) where a = (select max(b) from t); + * b. Filters generated by optimizer: `v1.a = 1 or v1.a = 2` + * select * from (select * from t) v1, v2 where (v1.a = 1 and v1.b = v2.b) or v1.a = 2; + * c. Filters push down by upper log plan + * + * case a and case b should be removed after they can be push down in the transformer + */ + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (expr->has_flag(CNT_DYNAMIC_PARAM) || + ObOptimizerUtil::find_item(get_plan()->get_new_or_quals(), expr) || + ObOptimizerUtil::find_item(get_plan()->get_pushdown_filters(), expr)) { + if (OB_FAIL(necessary_pushdown_quals.push_back(expr))) { + LOG_WARN("failed to push back", K(ret)); + } + } else { + if (OB_FAIL(unnecessary_pushdown_quals.push_back(expr))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + } + return ret; +} + int ObJoinOrder::generate_normal_subquery_paths() { int ret = OB_SUCCESS; @@ -7434,6 +7483,7 @@ int ObJoinOrder::generate_normal_subquery_paths() ObSQLSessionInfo *session_info = NULL; ObRawExprFactory *expr_factory = NULL; ObSEArray candi_pushdown_quals; + ObSEArray candi_nonpushdown_quals; helper.is_inner_path_ = false; LOG_TRACE("start to generate normal subquery path", K(table_id_)); if (OB_ISNULL(get_plan()) || OB_ISNULL(parent_stmt = get_plan()->get_stmt()) || @@ -7445,15 +7495,21 @@ int ObJoinOrder::generate_normal_subquery_paths() } else if (OB_ISNULL(helper.child_stmt_ = table_item->ref_query_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is null", K(ret)); + } else if (OB_FAIL(extract_necessary_pushdown_quals(get_restrict_infos(), + candi_pushdown_quals, + candi_nonpushdown_quals))) { + LOG_WARN("failed to classify push down quals", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::pushdown_and_rename_filter_into_subquery(*parent_stmt, *helper.child_stmt_, table_id_, get_plan()->get_optimizer_context(), - get_restrict_infos(), + candi_pushdown_quals, helper.pushdown_filters_, helper.filters_, /*check_match_index*/false))) { LOG_WARN("failed to push down filter into subquery", K(ret)); + } else if (OB_FAIL(append(helper.filters_, candi_nonpushdown_quals))) { + LOG_WARN("failed to append", K(ret)); } else if (OB_FAIL(generate_subquery_paths(helper))) { LOG_WARN("failed to generate subquery path", K(ret)); } @@ -13101,6 +13157,7 @@ int ObJoinOrder::generate_inner_subquery_paths(const ObIArray &join int ret = OB_SUCCESS; const ObDMLStmt *parent_stmt = NULL; ObSEArray pushdown_quals; + ObSEArray dummy; LOG_TRACE("OPT:start to generate inner subquery path", K(right_tree.table_id_), K(join_relids)); if (OB_ISNULL(get_plan()) || OB_ISNULL(parent_stmt = get_plan()->get_stmt())) { ret = OB_ERR_UNEXPECTED; @@ -13134,6 +13191,8 @@ int ObJoinOrder::generate_inner_subquery_paths(const ObDMLStmt &parent_stmt, bool can_pushdown = false; ObSEArray param_pushdown_quals; ObSEArray candi_pushdown_quals; + ObSEArray neccesary_pushdown_quals; + ObSEArray candi_nonpushdown_quals; ObSEArray nl_params; ObSQLSessionInfo *session_info = NULL; ObRawExprFactory *expr_factory = NULL; @@ -13153,10 +13212,14 @@ int ObJoinOrder::generate_inner_subquery_paths(const ObDMLStmt &parent_stmt, pushdown_quals, param_pushdown_quals))) { LOG_WARN("failed to extract params for inner path", K(ret)); + } else if (OB_FAIL(extract_necessary_pushdown_quals(param_pushdown_quals, + neccesary_pushdown_quals, + candi_nonpushdown_quals))) { + LOG_WARN("failed to classify push down quals", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::pushdown_filter_into_subquery(parent_stmt, *child_stmt, get_plan()->get_optimizer_context(), - param_pushdown_quals, + neccesary_pushdown_quals, candi_pushdown_quals, helper.filters_, can_pushdown))) { @@ -13173,6 +13236,8 @@ int ObJoinOrder::generate_inner_subquery_paths(const ObDMLStmt &parent_stmt, candi_pushdown_quals, helper.pushdown_filters_))) { LOG_WARN("failed to rename pushdown filter", K(ret)); + } else if (append(helper.filters_, candi_nonpushdown_quals)) { + LOG_WARN("failed to append", K(ret)); } else if (OB_FAIL(generate_subquery_paths(helper))) { LOG_WARN("failed to generate subquery path", K(ret)); } else if (OB_FAIL(check_and_fill_inner_path_info(helper, diff --git a/src/sql/optimizer/ob_join_order.h b/src/sql/optimizer/ob_join_order.h index 949810f9a9..c40af2ee63 100644 --- a/src/sql/optimizer/ob_join_order.h +++ b/src/sql/optimizer/ob_join_order.h @@ -1702,6 +1702,10 @@ struct NullAwareAntiJoinInfo { int compute_base_table_property(uint64_t table_id, uint64_t ref_table_id); + int extract_necessary_pushdown_quals(ObIArray &candi_quals, + ObIArray &necessary_pushdown_quals, + ObIArray &unnecessary_pushdown_quals); + /** * @brief generate_subquery_path * 生成子查询路径 diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index ef8ce81c4c..d19f877449 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -3830,6 +3830,8 @@ int ObLogPlan::try_split_or_qual(const ObRelIds &table_ids, /* do nothing */ } else if (OB_FAIL(table_quals.push_back(new_expr))) { LOG_WARN("failed to push back new expr", K(ret)); + } else if (OB_FAIL(new_or_quals_.push_back(new_expr))) { + LOG_WARN("failed to push back expr", K(ret)); } return ret; } diff --git a/src/sql/optimizer/ob_log_plan.h b/src/sql/optimizer/ob_log_plan.h index 2f49f9abf6..80e6bbedeb 100644 --- a/src/sql/optimizer/ob_log_plan.h +++ b/src/sql/optimizer/ob_log_plan.h @@ -1336,6 +1336,8 @@ public: int perform_gather_stat_replace(ObLogicalOperator *op); + common::ObIArray &get_new_or_quals() { return new_or_quals_; } + protected: virtual int generate_normal_raw_plan() = 0; virtual int generate_dblink_raw_plan(); @@ -1883,6 +1885,7 @@ private: common::ObSEArray onetime_params_; common::ObSEArray, 4, common::ModulePageAllocator, true > onetime_replaced_exprs_; + common::ObSEArray new_or_quals_; DISALLOW_COPY_AND_ASSIGN(ObLogPlan); }; diff --git a/tools/deploy/mysql_test/test_suite/optimizer/r/mysql/union_sort_opt.result b/tools/deploy/mysql_test/test_suite/optimizer/r/mysql/union_sort_opt.result index 28c4d8c7d6..80cfb0319d 100644 --- a/tools/deploy/mysql_test/test_suite/optimizer/r/mysql/union_sort_opt.result +++ b/tools/deploy/mysql_test/test_suite/optimizer/r/mysql/union_sort_opt.result @@ -1830,20 +1830,20 @@ EXPLAIN SELECT col_bigint, col_bigint_signed, col_bigint_unsigned, col_char_20, pk) TUT WHERE pk in (9727744 ,7826688 ,1657856 , 55039 , 50631) ORDER BY col_bigint, col_bigint_signed, col_bigint_unsigned, col_char_20, col_decimal_20_0, col_decimal_20_0_signed, col_decimal_20_0_unsigned, col_timestamp_6, pk; Query Plan -=============================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------------------------- -|0 |SORT | |1 |50 | -|1 |└─SUBPLAN SCAN |TUT |6 |48 | -|2 | └─MERGE UNION DISTINCT | |6 |48 | -|3 | ├─TABLE FULL SCAN |table2_bigint(Reverse)|5 |6 | -|4 | └─SORT | |1 |41 | -|5 | └─MERGE UNION DISTINCT | |6 |39 | -|6 | ├─TABLE GET |table2_bigint |5 |26 | -|7 | └─SORT | |1 |11 | -|8 | └─TOP-N SORT | |1 |11 | -|9 | └─TABLE FULL SCAN|table100_bigint |1 |10 | -=============================================================================== +============================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------------------- +|0 |SORT | |5 |52 | +|1 |└─SUBPLAN SCAN |TUT |5 |50 | +|2 | └─MERGE UNION DISTINCT | |11 |50 | +|3 | ├─MERGE UNION DISTINCT | |6 |39 | +|4 | │ ├─TABLE GET |table2_bigint |5 |26 | +|5 | │ └─SORT | |1 |11 | +|6 | │ └─TOP-N SORT | |1 |11 | +|7 | │ └─TABLE FULL SCAN|table100_bigint |1 |10 | +|8 | └─SORT | |5 |8 | +|9 | └─TABLE FULL SCAN |table2_bigint(Reverse)|5 |6 | +============================================================================= Outputs & filters: ------------------------------------- 0 - output([TUT.col_bigint], [TUT.col_bigint_signed], [TUT.col_bigint_unsigned], [TUT.col_char_20], [TUT.col_decimal_20_0], [TUT.col_decimal_20_0_signed], @@ -1851,44 +1851,42 @@ Outputs & filters: sort_keys([TUT.col_bigint, ASC], [TUT.col_bigint_signed, ASC], [TUT.col_bigint_unsigned, ASC], [TUT.col_char_20, ASC], [TUT.col_decimal_20_0, ASC], [TUT.col_decimal_20_0_signed, ASC], [TUT.col_decimal_20_0_unsigned, ASC], [TUT.col_timestamp_6, ASC], [TUT.pk, ASC]) 1 - output([TUT.pk], [TUT.col_bigint], [TUT.col_bigint_signed], [TUT.col_bigint_unsigned], [TUT.col_char_20], [TUT.col_decimal_20_0], [TUT.col_decimal_20_0_signed], - [TUT.col_decimal_20_0_unsigned], [TUT.col_timestamp_6]), filter(nil), rowset=16 + [TUT.col_decimal_20_0_unsigned], [TUT.col_timestamp_6]), filter([TUT.pk IN (9727744, 7826688, 1657856, 55039, 50631)]), rowset=16 access([TUT.pk], [TUT.col_bigint], [TUT.col_bigint_signed], [TUT.col_bigint_unsigned], [TUT.col_char_20], [TUT.col_decimal_20_0], [TUT.col_decimal_20_0_signed], [TUT.col_decimal_20_0_unsigned], [TUT.col_timestamp_6]) - 2 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])], [UNION([6])], [UNION([7])], [UNION([8])], [UNION([9])]), filter([UNION([9]) - IN (9727744, 7826688, 1657856, 55039, 50631)]), rowset=16 - 3 - output([table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], - [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_timestamp_6], [table2_bigint.pk]), filter([cast(table2_bigint.col_decimal_20_0_unsigned, - DECIMAL(20, 0)) != cast(99999, DECIMAL(5, 0))]), rowset=16 - access([table2_bigint.pk], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], - [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_timestamp_6]), partitions(p0) - limit(5), offset(1), is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([table2_bigint.pk]), range(MIN ; MAX)always true - 4 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])], [UNION([6])], [UNION([7])], [UNION([8])], [UNION([9])]), filter(nil), rowset=16 - sort_keys([UNION([9]), DESC], [UNION([1]), ASC], [UNION([2]), ASC], [UNION([3]), ASC], [UNION([4]), ASC], [UNION([5]), ASC], [UNION([6]), ASC], [UNION([7]), - ASC], [UNION([8]), ASC]) - 5 - output([UNION([9])], [UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])], [UNION([6])], [UNION([7])], [UNION([8])]), filter([UNION([9]) - IN (9727744, 7826688, 1657856, 55039, 50631)]), rowset=16 - 6 - output([table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], + 2 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])], [UNION([6])], [UNION([7])], [UNION([8])], [UNION([9])]), filter(nil), rowset=16 + 3 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])], [UNION([6])], [UNION([7])], [UNION([8])], [UNION([9])]), filter(nil), rowset=16 + 4 - output([table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_timestamp_6], [table2_bigint.pk]), filter(nil), rowset=16 access([table2_bigint.pk], [table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_timestamp_6]), partitions(p0) is_index_back=false, is_global_index=false, range_key([table2_bigint.pk]), range[9727744 ; 9727744], [7826688 ; 7826688], [1657856 ; 1657856], [55039 ; 55039], [50631 ; 50631], - range_cond([table2_bigint.pk IN (9727744, 7826688, 1657856, 55039, 50631)], [table2_bigint.pk IN (9727744, 7826688, 1657856, 55039, 50631)]) - 7 - output([table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], [table100_bigint.col_decimal_20_0], + range_cond([table2_bigint.pk IN (9727744, 7826688, 1657856, 55039, 50631)]) + 5 - output([table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], [table100_bigint.col_decimal_20_0], [table100_bigint.col_decimal_20_0_signed], [table100_bigint.col_decimal_20_0_unsigned], [table100_bigint.col_timestamp_6], [table100_bigint.pk]), filter(nil), rowset=16 sort_keys([table100_bigint.pk, ASC]) - 8 - output([table100_bigint.pk], [table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], + 6 - output([table100_bigint.pk], [table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], [table100_bigint.col_decimal_20_0], [table100_bigint.col_decimal_20_0_signed], [table100_bigint.col_decimal_20_0_unsigned], [table100_bigint.col_timestamp_6]), filter(nil), rowset=16 sort_keys([table100_bigint.col_bigint_signed, ASC], [table100_bigint.col_decimal_20_0_signed, ASC], [table100_bigint.col_decimal_20_0, ASC], [table100_bigint.pk, DESC]), topn(7) - 9 - output([table100_bigint.pk], [table100_bigint.col_decimal_20_0_signed], [table100_bigint.col_decimal_20_0], [table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], + 7 - output([table100_bigint.pk], [table100_bigint.col_decimal_20_0_signed], [table100_bigint.col_decimal_20_0], [table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], [table100_bigint.col_decimal_20_0_unsigned], [table100_bigint.col_timestamp_6]), filter([table100_bigint.col_decimal_20_0_signed = cast(ROUND(SIGN(table100_bigint.col_decimal_20_0)), DECIMAL(-1, 0))]), rowset=16 access([table100_bigint.pk], [table100_bigint.col_decimal_20_0_signed], [table100_bigint.col_decimal_20_0], [table100_bigint.col_bigint], [table100_bigint.col_bigint_signed], [table100_bigint.col_bigint_unsigned], [table100_bigint.col_char_20], [table100_bigint.col_decimal_20_0_unsigned], [table100_bigint.col_timestamp_6]), partitions(p0) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([table100_bigint.pk]), range(MIN ; MAX)always true + 8 - output([table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], + [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_timestamp_6], [table2_bigint.pk]), filter(nil), rowset=16 + sort_keys([table2_bigint.pk, ASC]) + 9 - output([table2_bigint.pk], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], + [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_timestamp_6]), filter([cast(table2_bigint.col_decimal_20_0_unsigned, + DECIMAL(20, 0)) != cast(99999, DECIMAL(5, 0))]), rowset=16 + access([table2_bigint.pk], [table2_bigint.col_decimal_20_0_unsigned], [table2_bigint.col_bigint], [table2_bigint.col_bigint_signed], [table2_bigint.col_bigint_unsigned], + [table2_bigint.col_char_20], [table2_bigint.col_decimal_20_0], [table2_bigint.col_decimal_20_0_signed], [table2_bigint.col_timestamp_6]), partitions(p0) + limit(5), offset(1), is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([table2_bigint.pk]), range(MIN ; MAX)always true SELECT col_bigint, col_bigint_signed, col_bigint_unsigned, col_char_20, col_decimal_20_0, col_decimal_20_0_signed, col_decimal_20_0_unsigned, col_timestamp_6, pk FROM (