add a check rule when trigger groupby pullup

This commit is contained in:
ChangerR 2023-05-15 10:11:40 +00:00 committed by ob-robot
parent dbaf4e2210
commit 2f6eea23d6
14 changed files with 369 additions and 73 deletions

View File

@ -15,6 +15,8 @@
#include "sql/rewrite/ob_transform_utils.h"
#include "sql/resolver/expr/ob_raw_expr_util.h"
#include "sql/optimizer/ob_optimizer_util.h"
#include "sql/optimizer/ob_log_subplan_scan.h"
#include "sql/optimizer/ob_log_table_scan.h"
#include "common/ob_smart_call.h"
using namespace oceanbase::sql;
@ -51,6 +53,7 @@ int ObTransformGroupByPullup::transform_one_stmt(common::ObIArray<ObParentDMLStm
{
int ret = OB_SUCCESS;
ObSEArray<PullupHelper, 4> valid_views;
ObCostBasedPullupCtx pullup_ctx;
ObTryTransHelper try_trans_helper;
if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) {
ret = OB_ERR_UNEXPECTED;
@ -66,7 +69,6 @@ int ObTransformGroupByPullup::transform_one_stmt(common::ObIArray<ObParentDMLStm
int64_t view_id = valid_views.at(i).table_id_;
TableItem *view = NULL;
LOG_DEBUG("begin pull up", K(valid_views.count()), K(valid_views.at(i).need_merge_));
if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_,
*ctx_->expr_factory_,
stmt,
@ -75,13 +77,14 @@ int ObTransformGroupByPullup::transform_one_stmt(common::ObIArray<ObParentDMLStm
} else if (OB_ISNULL(view = trans_stmt->get_table_item_by_id(view_id))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("view is null", K(ret));
} else if (OB_FALSE_IT(pullup_ctx.view_talbe_id_ = valid_views.at(i).table_id_)) {
} else if (OB_FAIL(get_trans_view(trans_stmt, view_stmt))) {
LOG_WARN("failed to get transform view", K(ret));
} else if (OB_FAIL(do_groupby_pull_up(view_stmt, valid_views.at(i)))) {
LOG_WARN("failed to do pull up group by", K(ret));
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
valid_views.at(i).need_merge_,
trans_happened))) {
valid_views.at(i).need_merge_, true,
trans_happened, &pullup_ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (!trans_happened) {
LOG_DEBUG("pull up not happen", K(trans_happened));
@ -909,57 +912,24 @@ int ObTransformGroupByPullup::wrap_case_when(ObSelectStmt &child_stmt,
}
int ObTransformGroupByPullup::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid)
int ObTransformGroupByPullup::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid)
{
int ret = OB_SUCCESS;
ObCostBasedPushDownCtx *push_down_ctx = static_cast<ObCostBasedPushDownCtx *>(check_ctx);
if (OB_ISNULL(plan) || OB_ISNULL(push_down_ctx)) {
ObCostBasedPullupCtx *ctx = static_cast<ObCostBasedPullupCtx*>(check_ctx);
if (OB_ISNULL(ctx) || OB_ISNULL(plan)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null param", K(ret));
} else if (OB_FAIL(check_nl_operator(plan->get_plan_root(), push_down_ctx, is_valid))) {
LOG_WARN("check nl operator failed", K(ret));
}
return ret;
}
int ObTransformGroupByPullup::check_nl_operator(ObLogicalOperator *op, ObCostBasedPushDownCtx *push_down_ctx, bool &is_valid)
{
int ret = OB_SUCCESS;
const int64_t stmt_id = push_down_ctx->stmt_id_;
ObLogJoin *join = NULL;
if (OB_ISNULL(op) || OB_ISNULL(op->get_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("op is null", K(ret));
} else if (stmt_id == op->get_stmt()->get_stmt_id()) {
if (log_op_def::LOG_JOIN == op->get_type()) {
if (OB_ISNULL(join = static_cast<ObLogJoin *>(op))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("static cast failed", K(ret));
} else if (JoinAlgo::NESTED_LOOP_JOIN == join->get_join_algo() && join->get_nl_params().count() > 0) {
ObLogicalOperator *right_table = join->get_right_table();
bool exist_group_by_op = false;
if (OB_ISNULL(right_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("right table is null", K(ret));
} else if (push_down_ctx->new_table_relids_.overlap(right_table->get_table_set())) {
if (OB_FAIL(has_group_by_op(right_table, exist_group_by_op))) {
LOG_WARN("has group by op failed", K(ret));
} else {
is_valid = !exist_group_by_op;
}
}
} else {}
} else {}
} else {}
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < op->get_num_of_child(); i++) {
if (OB_FAIL(SMART_CALL(check_nl_operator(op->get_child(i), push_down_ctx, is_valid)))) {
LOG_WARN("check nl operator failed", K(ret));
}
} else if (is_trans_plan) {
//do nothing
} else if (OB_FAIL(check_original_plan_validity(plan->get_plan_root(),
ctx->view_talbe_id_,
is_valid))) {
LOG_WARN("failed to check plan validity", K(ret));
}
return ret;
}
int ObTransformGroupByPullup::has_group_by_op(ObLogicalOperator *op, bool &bret)
{
int ret = OB_SUCCESS;
@ -1099,3 +1069,284 @@ int ObTransformGroupByPullup::need_transform(const common::ObIArray<ObParentDMLS
LOG_DEBUG("need trans pullup", K(need_trans));
return ret;
}
int ObTransformGroupByPullup::check_original_plan_validity(ObLogicalOperator* root,
uint64_t view_table_id,
bool &is_valid)
{
int ret = OB_SUCCESS;
TableItem *table_item = NULL;
ObSEArray<ObLogicalOperator*, 4> parent_ops;
ObLogicalOperator *subplan = NULL;
ObSEArray<ObRawExpr*, 4> column_exprs;
ObSEArray<ObRawExpr*, 4> select_exprs;
ObSEArray<ObRawExpr*, 4> group_exprs;
uint64_t groupby_nopushdown_cut_ratio = 1;
double group_ndv = 1.0;
double card = 1.0;
bool has_stats = true;
const ObSelectStmt *child_stmt = NULL;
if (OB_ISNULL(root) ||
OB_ISNULL(ctx_) ||
OB_ISNULL(ctx_->session_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(root), K(ret));
} else if (OB_FAIL(find_operator(root, parent_ops, view_table_id, subplan))) {
LOG_WARN("failed to find subplan scan operator", K(root), K(view_table_id), K(ret));
} else if (OB_ISNULL(subplan) || parent_ops.empty()) {
//do nothing
} else if (OB_UNLIKELY(subplan->get_num_of_child() == 0) ||
OB_ISNULL(subplan = subplan->get_child(ObLogicalOperator::first_child)) ||
OB_ISNULL(subplan->get_stmt()) ||
OB_UNLIKELY(!subplan->get_stmt()->is_select_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FALSE_IT(child_stmt = static_cast<const ObSelectStmt*>(subplan->get_stmt()))) {
// do nothing
} else if (OB_FAIL(check_all_table_has_statistics(subplan, has_stats))) {
LOG_WARN("failed to check all table has statistics", K(ret));
} else if (!has_stats) {
is_valid = false;
RESUME_OPT_TRACE
OPT_TRACE("check original plan has statistics:", has_stats);
STOP_OPT_TRACE
} else if (OB_FAIL(extract_columns_in_join_conditions(parent_ops,
view_table_id,
column_exprs))) {
LOG_WARN("failed to extract columns in join conditions", K(ret));
} else if (OB_FAIL(ObTransformUtils::convert_column_expr_to_select_expr(column_exprs,
*child_stmt,
select_exprs))) {
LOG_WARN("failed to convert column exprs to select exprs", K(ret));
} else if (OB_FAIL(get_group_by_subset(select_exprs,
child_stmt->get_group_exprs(),
group_exprs))) {
LOG_WARN("failed to get group by subset", K(ret));
} else if (OB_FAIL(ctx_->session_info_->get_sys_variable(share::SYS_VAR__GROUPBY_NOPUSHDOWN_CUT_RATIO,
groupby_nopushdown_cut_ratio))) {
LOG_WARN("failed to get session variable", K(ret));
} else if (OB_FAIL(calc_group_exprs_ndv(group_exprs, subplan, group_ndv, card))) {
LOG_WARN("failed to check group exprs", K(ret));
} else {
double expansion_rate = card / group_ndv;
is_valid = expansion_rate < groupby_nopushdown_cut_ratio;
LOG_TRACE("check original plan", K(is_valid), K(group_exprs), K(group_ndv), K(expansion_rate));
RESUME_OPT_TRACE
OPT_TRACE("check original plan group by exprs:", group_exprs);
OPT_TRACE("check original plan group by ndv:", group_ndv);
OPT_TRACE("check original plan expansion rate:", expansion_rate);
STOP_OPT_TRACE
}
return ret;
}
int ObTransformGroupByPullup::find_operator(ObLogicalOperator* root,
ObIArray<ObLogicalOperator*> &parents,
uint64_t view_table_id,
ObLogicalOperator *&subplan_root)
{
int ret = OB_SUCCESS;
subplan_root = NULL;
if (OB_ISNULL(root)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null logical operator", K(ret));
} else if (log_op_def::LOG_SUBPLAN_SCAN == root->get_type() &&
static_cast<ObLogSubPlanScan *>(root)->get_subquery_id() == view_table_id) {
subplan_root = root;
} else {
for (int64_t i = 0; OB_SUCC(ret) && NULL == subplan_root && i < root->get_num_of_child(); ++i) {
ObLogicalOperator *child = root->get_child(i);
if (OB_FAIL(SMART_CALL(find_operator(child, parents, view_table_id, subplan_root)))) {
LOG_WARN("failed to find operator", K(ret));
} else if (NULL == subplan_root) {
//do nothing
} else if (parents.empty() ||
parents.at(0)->get_stmt() == root->get_stmt()) {
if (OB_FAIL(parents.push_back(root))) {
LOG_WARN("failed to push back operator", K(ret));
}
}
}
}
return ret;
}
int ObTransformGroupByPullup::calc_group_exprs_ndv(const ObIArray<ObRawExpr*> &group_exprs,
ObLogicalOperator *subplan_root,
double &group_ndv,
double &card)
{
int ret = OB_SUCCESS;
ObLogPlan *plan = NULL;
ObLogicalOperator *child_op = subplan_root;
group_ndv = 1.0;
if (OB_ISNULL(subplan_root) ||
OB_ISNULL(plan = subplan_root->get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null logical operator", K(ret));
} else if (OB_FAIL(find_base_operator(child_op))) {
LOG_WARN("failed to find base operator", K(ret));
} else if (OB_ISNULL(child_op)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null logical operator", K(ret));
} else {
card = child_op->get_card();
plan->get_selectivity_ctx().init_op_ctx(&child_op->get_output_equal_sets(), card);
if (group_exprs.empty()) {
group_ndv = 1.0;
} else if (OB_FAIL(ObOptSelectivity::calculate_distinct(plan->get_update_table_metas(),
plan->get_selectivity_ctx(),
group_exprs,
card,
group_ndv))) {
LOG_WARN("failed to calculate distinct", K(ret));
} else { /* do nothing */ }
}
return ret;
}
int ObTransformGroupByPullup::find_base_operator(ObLogicalOperator *&root)
{
int ret = OB_SUCCESS;
while (OB_SUCC(ret) && root != NULL &&
(root->get_type() ==log_op_def::LOG_GROUP_BY ||
root->get_type() == log_op_def::LOG_EXCHANGE)) {
if (OB_UNLIKELY(root->get_num_of_child() != 1) ||
OB_ISNULL(root = root->get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null logical operator", K(ret));
}
}
return ret;
}
int ObTransformGroupByPullup::extract_columns_in_join_conditions(
ObIArray<ObLogicalOperator*> &parent_ops,
uint64_t table_id,
ObIArray<ObRawExpr*> &column_exprs)
{
int ret = OB_SUCCESS;
ObLogicalOperator *parent = NULL;
ObSEArray<ObRawExpr*, 4> tmp_column_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < parent_ops.count(); ++i) {
if (OB_ISNULL(parent = parent_ops.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(parent), K(ret));
} else if (log_op_def::LOG_JOIN == parent->get_type()) {
ObLogJoin *join_op = static_cast<ObLogJoin*>(parent);
if (HASH_JOIN == join_op->get_join_algo() ||
MERGE_JOIN == join_op->get_join_algo()) {
tmp_column_exprs.reuse();
if (OB_FAIL(ObRawExprUtils::extract_column_exprs(join_op->get_equal_join_conditions(),
table_id,
tmp_column_exprs))) {
LOG_WARN("failed to extract column exprs", K(ret));
} else if (OB_FAIL(append_array_no_dup(column_exprs, tmp_column_exprs))) {
LOG_WARN("failed to append array no dup", K(ret));
}
} else if (NESTED_LOOP_JOIN == join_op->get_join_algo()) {
for (int64_t i = 0; OB_SUCC(ret) && i < join_op->get_other_join_conditions().count(); ++i) {
ObRawExpr *cond = NULL;
if (OB_ISNULL(cond = join_op->get_other_join_conditions().at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (!cond->has_flag(IS_JOIN_COND)) {
// do nothing
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(cond,
table_id,
tmp_column_exprs))) {
LOG_WARN("failed to extract column exprs", K(ret));
} else if (OB_FAIL(append_array_no_dup(column_exprs, tmp_column_exprs))) {
LOG_WARN("failed to append array no dup", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < join_op->get_nl_params().count(); ++i) {
tmp_column_exprs.reuse();
if (OB_ISNULL(join_op->get_nl_params().at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("nl param is null", K(ret));
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(join_op->get_nl_params().at(i)->get_ref_expr(),
table_id,
tmp_column_exprs))) {
LOG_WARN("failed to extract column exprs", K(ret));
} else if (OB_FAIL(append_array_no_dup(column_exprs, tmp_column_exprs))) {
LOG_WARN("failed to append array no dup", K(ret));
}
}
}
}
}
return ret;
}
int ObTransformGroupByPullup::get_group_by_subset(ObRawExpr *expr,
const ObIArray<ObRawExpr *> &group_exprs,
ObIArray<ObRawExpr *> &subset_group_exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(ret));
} else {
int64_t idx = -1;
if (expr->has_flag(IS_AGG) || expr->has_flag(IS_CONST)) {
//do nothing
} else if (OB_FAIL(ObTransformUtils::get_expr_idx(group_exprs, expr, idx))) {
LOG_WARN("get expr idx failed", K(ret));
} else if (idx == -1) { //not found
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) {
if (OB_FAIL(SMART_CALL(get_group_by_subset(expr->get_param_expr(i), group_exprs, subset_group_exprs)))) {
LOG_WARN("check group by subset faield", K(ret));
}
}
} else if (OB_FAIL(add_var_to_array_no_dup(subset_group_exprs, expr))) {
LOG_WARN("failed to add var to array no dump", K(ret));
}
}
return ret;
}
int ObTransformGroupByPullup::get_group_by_subset(ObIArray<ObRawExpr *> &exprs,
const ObIArray<ObRawExpr *> &group_exprs,
ObIArray<ObRawExpr *> &subset_group_exprs)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
if (OB_FAIL(get_group_by_subset(exprs.at(i), group_exprs,
subset_group_exprs))) {
LOG_WARN("check group by exprs failed", K(ret));
}
}
return ret;
}
int ObTransformGroupByPullup::check_all_table_has_statistics(ObLogicalOperator *op, bool &has_stats)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(op)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (op->get_type() == log_op_def::LOG_TABLE_SCAN) {
ObLogTableScan *table_scan = static_cast<ObLogTableScan*>(op);
ObLogPlan *plan = table_scan->get_plan();
OptTableMeta* meta = NULL;
if (OB_ISNULL(plan)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_ISNULL(meta = plan->get_basic_table_metas()
.get_table_meta_by_table_id(table_scan->get_table_id()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
has_stats = meta->get_version() > 0;
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && has_stats && i < op->get_num_of_child(); ++i) {
if (OB_FAIL(SMART_CALL(check_all_table_has_statistics(op->get_child(i), has_stats)))) {
LOG_WARN("failed to check all table has statistics", K(ret));
}
}
}
return ret;
}

View File

@ -42,7 +42,7 @@ public:
bool &trans_happened) override;
protected:
virtual int adjust_transform_types(uint64_t &transform_types) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid) override;
private:
struct PullupHelper {
PullupHelper():
@ -77,10 +77,9 @@ private:
K_(need_merge));
};
struct ObCostBasedPushDownCtx {
ObCostBasedPushDownCtx() {};
int64_t stmt_id_;
ObSqlBitSet<> new_table_relids_;
struct ObCostBasedPullupCtx {
ObCostBasedPullupCtx() {};
uint64_t view_talbe_id_;
};
int check_groupby_validity(const ObSelectStmt &stmt, bool &is_valid);
@ -147,10 +146,6 @@ private:
ObRawExpr *not_null_column,
ObRawExpr *&expr);
int check_nl_operator(ObLogicalOperator *op,
ObCostBasedPushDownCtx *push_down_ctx,
bool &is_valid);
int has_group_by_op(ObLogicalOperator *op,
bool &bret);
@ -164,6 +159,37 @@ private:
const int64_t current_level,
const ObDMLStmt &stmt,
bool &need_trans) override;
int check_original_plan_validity(ObLogicalOperator* root,
uint64_t view_table_id,
bool &is_valid);
int find_operator(ObLogicalOperator* root,
ObIArray<ObLogicalOperator*> &parents,
uint64_t view_table_id,
ObLogicalOperator *&subplan_op);
int find_base_operator(ObLogicalOperator *&root);
int extract_columns_in_join_conditions(ObIArray<ObLogicalOperator*> &parent_ops,
uint64_t table_id,
ObIArray<ObRawExpr*> &column_exprs);
int get_group_by_subset(ObRawExpr *expr,
const ObIArray<ObRawExpr *> &group_exprs,
ObIArray<ObRawExpr *> &subset_group_exprs);
int get_group_by_subset(ObIArray<ObRawExpr *> &exprs,
const ObIArray<ObRawExpr *> &group_exprs,
ObIArray<ObRawExpr *> &subset_group_exprs);
int calc_group_exprs_ndv(const ObIArray<ObRawExpr*> &group_exprs,
ObLogicalOperator *subplan_root,
double &group_ndv,
double &card);
int check_all_table_has_statistics(ObLogicalOperator *op, bool &has_stats);
private:
// help functions
int64_t get_count_sum_num(const ObIArray<ObRawExpr *> &exprs)

View File

@ -92,7 +92,7 @@ int ObTransformGroupByPushdown::transform_one_stmt(common::ObIArray<ObParentDMLS
} else if (OB_FAIL(get_tables_from_params(*stmt, params, trans_tables))) {
LOG_WARN("get tables failed", K(ret));
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
NULL != myhint && myhint->is_enable_hint(),
NULL != myhint && myhint->is_enable_hint(), false,
trans_happened, &push_down_ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (!trans_happened) {
@ -1578,13 +1578,15 @@ int ObTransformGroupByPushdown::construct_transform_hint(ObDMLStmt &stmt, void *
return ret;
}
int ObTransformGroupByPushdown::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid)
int ObTransformGroupByPushdown::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid)
{
int ret = OB_SUCCESS;
ObCostBasedPushDownCtx *push_down_ctx = static_cast<ObCostBasedPushDownCtx *>(check_ctx);
if (OB_ISNULL(plan) || OB_ISNULL(push_down_ctx)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null param", K(ret));
} else if (!is_trans_plan) {
// do nothing
} else if (OB_FAIL(check_nl_operator(plan->get_plan_root(), push_down_ctx, is_valid))) {
LOG_WARN("check nl operator failed", K(ret));
}

View File

@ -42,7 +42,7 @@ public:
bool &trans_happened) override;
protected:
virtual int adjust_transform_types(uint64_t &transform_types) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid) override;
private:
struct PushDownParam {
ObSqlBitSet<> table_bit_index_;

View File

@ -169,7 +169,7 @@ int ObTransformOrExpansion::transform_in_where_conditon(ObIArray<ObParentDMLStmt
} else if (OB_FAIL(merge_stmt(trans_stmt, spj_stmt, transformed_union_stmt))) {
LOG_WARN("failed to merge stmt", K(ret));
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
NULL != ctx.hint_,
NULL != ctx.hint_, false,
trans_happened, &ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (trans_happened && OB_FAIL(add_transform_hint(*trans_stmt, &ctx))) {
@ -266,7 +266,7 @@ int ObTransformOrExpansion::transform_in_semi_info(ObIArray<ObParentDMLStmt> &pa
} else if (OB_FAIL(merge_stmt(trans_stmt, spj_stmt, transformed_union_stmt))) {
LOG_WARN("failed to merge stmt", K(ret));
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
NULL != ctx.hint_,
NULL != ctx.hint_, false,
trans_happened, &ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (trans_happened && OB_FAIL(add_transform_hint(*trans_stmt, &ctx))) {
@ -431,7 +431,7 @@ int ObTransformOrExpansion::try_do_transform_inner_join(ObIArray<ObParentDMLStmt
} else if (OB_FALSE_IT(NULL == view_table ? origin_trans_stmt = trans_stmt
: view_table->ref_query_ = static_cast<ObSelectStmt*>(trans_stmt))) {
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, origin_trans_stmt,
NULL != ctx.hint_,
NULL != ctx.hint_, false,
trans_happened, &ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (trans_happened && OB_FAIL(add_transform_hint(*trans_stmt, &ctx))) {
@ -548,7 +548,7 @@ int ObTransformOrExpansion::try_do_transform_left_join(ObIArray<ObParentDMLStmt>
} else if (OB_FALSE_IT(NULL == view_table ? trans_stmt = trans_ref_query
: view_table->ref_query_ = trans_ref_query)) {
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
NULL != ctx.hint_,
NULL != ctx.hint_, false,
trans_happened, &ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (trans_happened && OB_FAIL(add_transform_hint(*trans_stmt, &ctx))) {
@ -2584,7 +2584,7 @@ int ObTransformOrExpansion::preprocess_or_condition(ObSelectStmt &stmt,
5. outer/semi/anti join: use nlj with exec param push down
or use merge/hash and origin plan is nlj
*/
int ObTransformOrExpansion::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid)
int ObTransformOrExpansion::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid)
{
int ret = OB_SUCCESS;
ObCostBasedRewriteCtx *ctx = static_cast<ObCostBasedRewriteCtx *>(check_ctx);
@ -2593,6 +2593,8 @@ int ObTransformOrExpansion::is_expected_plan(ObLogPlan *plan, void *check_ctx, b
if (OB_ISNULL(ctx) || OB_ISNULL(plan)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null param", K(ret));
} else if (!is_trans_plan) {
// do nothing
} else if (OB_FAIL(find_trans_log_set(plan->get_plan_root(), ctx->trans_id_, log_set))) {
LOG_WARN("failed to get join operator", K(ret));
} else if (NULL == log_set) {

View File

@ -111,7 +111,7 @@ public:
bool &trans_happened) override;
protected:
virtual int adjust_transform_types(uint64_t &transform_types) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid) override;
virtual int transform_one_stmt_with_outline(common::ObIArray<ObParentDMLStmt> &parent_stmts,
ObDMLStmt *&stmt,
bool &trans_happened) override;

View File

@ -285,6 +285,7 @@ int ObTransformRule::accept_transform(common::ObIArray<ObParentDMLStmt> &parent_
ObDMLStmt *&stmt,
ObDMLStmt *trans_stmt,
bool force_accept,
bool check_original_plan,
bool &trans_happened,
void *check_ctx /* = NULL*/)
{
@ -293,7 +294,7 @@ int ObTransformRule::accept_transform(common::ObIArray<ObParentDMLStmt> &parent_
trans_happened = false;
ObDMLStmt *top_stmt = parent_stmts.empty() ? stmt : parent_stmts.at(0).stmt_;
bool is_expected = false;
bool dummy = false;
bool is_original_expected = false;
ObDMLStmt *tmp1 = NULL;
ObDMLStmt *tmp2 = NULL;
cost_based_trans_tried_ = true;
@ -308,11 +309,14 @@ int ObTransformRule::accept_transform(common::ObIArray<ObParentDMLStmt> &parent_
} else if (OB_FAIL(evaluate_cost(parent_stmts, trans_stmt, true,
trans_stmt_cost, is_expected, check_ctx))) {
LOG_WARN("failed to evaluate cost for the transformed stmt", K(ret));
} else if (stmt_cost_ >= 0 || !is_expected) {
} else if ((!check_original_plan && stmt_cost_ >= 0) || !is_expected) {
trans_happened = is_expected && trans_stmt_cost < stmt_cost_;
} else if (OB_FAIL(evaluate_cost(parent_stmts, stmt, false,
stmt_cost_, dummy, NULL))) {
stmt_cost_, is_original_expected,
check_original_plan ? check_ctx : NULL))) {
LOG_WARN("failed to evaluate cost for the origin stmt", K(ret));
} else if (!is_original_expected) {
trans_happened = is_original_expected;
} else {
trans_happened = trans_stmt_cost < stmt_cost_;
}
@ -324,6 +328,7 @@ int ObTransformRule::accept_transform(common::ObIArray<ObParentDMLStmt> &parent_
OPT_TRACE("before transform cost:", stmt_cost_);
OPT_TRACE("after transform cost:", trans_stmt_cost);
OPT_TRACE("is expected plan:", is_expected);
OPT_TRACE("is expected original plan:", is_original_expected);
LOG_TRACE("reject transform because the cost is increased or the query plan is unexpected",
K_(ctx_->is_set_stmt_oversize), K_(stmt_cost), K(trans_stmt_cost), K(is_expected));
} else if (OB_FAIL(adjust_transformed_stmt(parent_stmts, trans_stmt, tmp1, tmp2))) {
@ -344,10 +349,11 @@ int ObTransformRule::accept_transform(common::ObIArray<ObParentDMLStmt> &parent_
return ret;
}
int ObTransformRule::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid)
int ObTransformRule::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid)
{
UNUSED(plan);
UNUSED(check_ctx);
UNUSED(is_trans_plan);
is_valid = false;
return OB_SUCCESS;
}
@ -415,7 +421,7 @@ int ObTransformRule::evaluate_cost(common::ObIArray<ObParentDMLStmt> &parent_stm
LOG_WARN("failed to get optimization cost", K(ret));
} else if (NULL == check_ctx) {
// do nothing
} else if (OB_FAIL(is_expected_plan(plan, check_ctx, is_expected))) {
} else if (OB_FAIL(is_expected_plan(plan, check_ctx, is_trans_stmt, is_expected))) {
LOG_WARN("failed to check transformed plan", K(ret));
}
}

View File

@ -350,6 +350,7 @@ protected:
ObDMLStmt *&stmt,
ObDMLStmt *trans_stmt,
bool force_accept,
bool check_original_plan,
bool &trans_happened,
void *check_ctx = NULL);
@ -423,6 +424,7 @@ private:
virtual int is_expected_plan(ObLogPlan *plan,
void *check_ctx,
bool is_trans_plan,
bool& is_valid);
bool skip_move_trans_loc() const

View File

@ -94,6 +94,7 @@ int ObTransformSemiToInner::transform_one_stmt(
LOG_TRACE("semi join can not transform to inner join", K(*semi_info));
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
!need_check_cost || ctx.hint_force_,
false,
accepted, &ctx))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (!accepted) {
@ -1455,7 +1456,7 @@ int ObTransformSemiToInner::is_ignore_semi_info(const uint64_t semi_id, bool &ig
return ret;
}
int ObTransformSemiToInner::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid)
int ObTransformSemiToInner::is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid)
{
int ret = OB_SUCCESS;
ObCostBasedRewriteCtx *ctx = static_cast<ObCostBasedRewriteCtx *>(check_ctx);
@ -1465,6 +1466,8 @@ int ObTransformSemiToInner::is_expected_plan(ObLogPlan *plan, void *check_ctx, b
if (OB_ISNULL(ctx) || OB_ISNULL(plan)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null param", K(ret));
} else if (!is_trans_plan) {
//do nothing
} else if (ctx->is_multi_join_cond_) {
is_valid = true;
} else if (OB_FAIL(find_operator(plan->get_plan_root(),

View File

@ -45,7 +45,7 @@ public:
bool &trans_happened) override;
virtual int construct_transform_hint(ObDMLStmt &stmt, void *trans_params) override;
protected:
int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid) override;
int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool is_trans_plan, bool &is_valid) override;
private:
enum TransformFlag {TO_INNER = 1, TO_AGGR_INNER = 2, TO_INNER_GBY = 4};

View File

@ -90,7 +90,7 @@ int ObTransformSubqueryCoalesce::transform_one_stmt(common::ObIArray<ObParentDML
LOG_WARN("failed to append equal infos", K(ret));
} else if (OB_ISNULL(trans_stmt)) {
// do nothing
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt, false, is_happened))) {
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt, false, false, is_happened))) {
LOG_WARN("failed to accept transform", K(ret));
} else if (!is_happened) {
// do nothing

View File

@ -230,6 +230,7 @@ int ObTransformWinMagic::do_transform(common::ObIArray<ObParentDMLStmt> &parent_
stmt,
trans_stmt,
NULL != myhint && myhint->is_enable_hint(),
false,
accepted))) {
LOG_WARN("accept transform failed", K(ret));
} else if (!accepted) {

View File

@ -1,6 +1,8 @@
drop table if exists t1, t2;
create table t1 (c1 int, c2 int, c3 int);
create table t2 (c1 int, c2 int, c3 int);
call dbms_stats.gather_table_stats(NULL, 't1');
call dbms_stats.gather_table_stats(NULL, 't2');
explain select /*+ use_px parallel(2) use_hash(c d) */ * from (select a.c2, b.c3 from (select /*+ use_hash(a, b) */ c1, c2, count(*) c3 from t1 group by 1, 2) a, (select c1, c2, count(*) c3 from t1 group by 1, 2) b where a.c1 = b.c1) c, (select c1, c2, count(*) c3 from t1 group by 1, 2) d where c.c2 = d.c2;
Query Plan
====================================================================================

View File

@ -10,7 +10,8 @@ drop table if exists t1, t2;
create table t1 (c1 int, c2 int, c3 int);
create table t2 (c1 int, c2 int, c3 int);
call dbms_stats.gather_table_stats(NULL, 't1');
call dbms_stats.gather_table_stats(NULL, 't2');
# need material above hash join. (but root DFO not needed)
explain select /*+ use_px parallel(2) use_hash(c d) */ * from (select a.c2, b.c3 from (select /*+ use_hash(a, b) */ c1, c2, count(*) c3 from t1 group by 1, 2) a, (select c1, c2, count(*) c3 from t1 group by 1, 2) b where a.c1 = b.c1) c, (select c1, c2, count(*) c3 from t1 group by 1, 2) d where c.c2 = d.c2;