push cte preds when generate plan in cost based rewrite

This commit is contained in:
xianyu-w
2023-09-11 03:10:33 +00:00
committed by ob-robot
parent 73d139ebdb
commit 32bc1e3d3d
6 changed files with 94 additions and 9 deletions

View File

@ -91,7 +91,7 @@ int ObSqlTempTableInfo::collect_temp_tables(ObIAllocator &allocator,
temp_table_infos, query_ctx, do_collect_filter)))) { temp_table_infos, query_ctx, do_collect_filter)))) {
LOG_WARN("failed to add all temp tables", K(ret)); LOG_WARN("failed to add all temp tables", K(ret));
} else if (OB_ISNULL(ptr = allocator.alloc(sizeof(ObSqlTempTableInfo)))) { } else if (OB_ISNULL(ptr = allocator.alloc(sizeof(ObSqlTempTableInfo)))) {
ret = OB_ERR_UNEXPECTED; ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("get unexpected null", K(ret)); LOG_WARN("get unexpected null", K(ret));
} else { } else {
temp_table_info = new (ptr) ObSqlTempTableInfo(); temp_table_info = new (ptr) ObSqlTempTableInfo();
@ -120,6 +120,45 @@ int ObSqlTempTableInfo::collect_temp_tables(ObIAllocator &allocator,
return ret; return ret;
} }
int ObSqlTempTableInfo::collect_specified_temp_table(ObIAllocator &allocator,
ObSelectStmt *specified_query,
const ObIArray<ObDMLStmt *> &upper_stmts,
const ObIArray<TableItem *> &table_items,
ObSqlTempTableInfo &temp_table_info)
{
int ret = OB_SUCCESS;
temp_table_info.reset();
if (OB_ISNULL(specified_query) ||
OB_UNLIKELY(upper_stmts.count() != table_items.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected param", K(specified_query), K(upper_stmts), K(table_items));;
} else {
temp_table_info.table_query_ = specified_query;
for (int64_t i = 0; OB_SUCC(ret) && i < upper_stmts.count(); i ++) {
TableItem *table = table_items.at(i);
ObDMLStmt *stmt = upper_stmts.at(i);
if (OB_ISNULL(stmt) || OB_ISNULL(table) ||
OB_UNLIKELY(specified_query != table->ref_query_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected params", K(table_items), K(upper_stmts));
} else {
TableInfo table_info;
table_info.upper_stmt_ = stmt;
table_info.table_item_ = table;
if (OB_FAIL(collect_temp_table_filters(table_info.upper_stmt_,
table_info.table_item_,
table_info.table_filters_,
table_info.filter_conditions_))) {
LOG_WARN("failed to collect temp table info", K(ret));
} else if (OB_FAIL(temp_table_info.table_infos_.push_back(table_info))) {
LOG_WARN("failed to push back table info", K(ret));
}
}
}
}
return ret;
}
int ObSqlTempTableInfo::collect_temp_table_filters(ObDMLStmt *stmt, int ObSqlTempTableInfo::collect_temp_table_filters(ObDMLStmt *stmt,
TableItem *table, TableItem *table,
ObIArray<ObRawExpr*> &table_filters, ObIArray<ObRawExpr*> &table_filters,

View File

@ -89,6 +89,14 @@ public:
table_plan_(NULL) {} table_plan_(NULL) {}
virtual ~ObSqlTempTableInfo() {} virtual ~ObSqlTempTableInfo() {}
void reset() {
temp_table_id_ = OB_INVALID_ID;
table_name_.reset();
table_query_ = NULL;
table_plan_ = NULL;
table_infos_.reset();
}
TO_STRING_KV(K_(temp_table_id), TO_STRING_KV(K_(temp_table_id),
K_(table_name), K_(table_name),
K_(table_infos)); K_(table_infos));
@ -98,6 +106,11 @@ public:
ObIArray<ObSqlTempTableInfo*> &temp_table_infos, ObIArray<ObSqlTempTableInfo*> &temp_table_infos,
ObQueryCtx *query_ctx, ObQueryCtx *query_ctx,
bool do_collect_filter); bool do_collect_filter);
static int collect_specified_temp_table(ObIAllocator &allocator,
ObSelectStmt *specified_query,
const ObIArray<ObDMLStmt *> &upper_stmts,
const ObIArray<TableItem *> &table_items,
ObSqlTempTableInfo &temp_table_info);
static int collect_temp_table_filters(ObDMLStmt *stmt, static int collect_temp_table_filters(ObDMLStmt *stmt,
TableItem *table, TableItem *table,
ObIArray<ObRawExpr*> &table_filters, ObIArray<ObRawExpr*> &table_filters,

View File

@ -90,7 +90,8 @@ int ObOptimizer::optimize(ObDMLStmt &stmt, ObLogPlan *&logical_plan)
int ObOptimizer::get_optimization_cost(ObDMLStmt &stmt, int ObOptimizer::get_optimization_cost(ObDMLStmt &stmt,
ObLogPlan *&plan, ObLogPlan *&plan,
double &cost) double &cost,
ObDMLStmt::TempTableInfo *current_temp_table_)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
cost = 0.0; cost = 0.0;
@ -106,8 +107,32 @@ int ObOptimizer::get_optimization_cost(ObDMLStmt &stmt,
LOG_WARN("failed to init env info", K(ret)); LOG_WARN("failed to init env info", K(ret));
} else if (OB_FAIL(generate_plan_for_temp_table(stmt))) { } else if (OB_FAIL(generate_plan_for_temp_table(stmt))) {
LOG_WARN("failed to generate plan for temp table", K(ret)); LOG_WARN("failed to generate plan for temp table", K(ret));
} else if (NULL != current_temp_table_) {
ObSqlTempTableInfo temp_table_info;
ObRawExpr *temp_table_nonwhere_filter = NULL;
ObRawExpr *temp_table_where_filter = NULL;
if (OB_UNLIKELY(!stmt.is_select_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("temp table query should be select stmt", K(stmt));
} else if (OB_FAIL(ObSqlTempTableInfo::collect_specified_temp_table(ctx_.get_allocator(),
current_temp_table_->temp_table_query_,
current_temp_table_->upper_stmts_,
current_temp_table_->table_items_,
temp_table_info))) {
LOG_WARN("failed to collect_specified_temp_table", K(ret));
} else if (OB_FAIL(try_push_down_temp_table_filter(temp_table_info,
temp_table_nonwhere_filter,
temp_table_where_filter,
static_cast<ObSelectStmt *>(&stmt)))) {
LOG_WARN("failed to push down filter for temp table", K(ret));
} else if (NULL != temp_table_where_filter &&
OB_FAIL(plan->get_pushdown_filters().push_back(temp_table_where_filter))) {
LOG_WARN("failed to push down filter", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(plan->generate_raw_plan())) { } else if (OB_FAIL(plan->generate_raw_plan())) {
LOG_WARN("failed to perform optimization", K(ret)); LOG_WARN("failed to perform optimization", K(ret));
} else { } else {
cost = plan->get_optimization_cost(); cost = plan->get_optimization_cost();
} }
@ -247,7 +272,8 @@ int ObOptimizer::generate_plan_for_temp_table(ObDMLStmt &stmt)
*/ */
int ObOptimizer::try_push_down_temp_table_filter(ObSqlTempTableInfo &info, int ObOptimizer::try_push_down_temp_table_filter(ObSqlTempTableInfo &info,
ObRawExpr *&nonwhere_filter, ObRawExpr *&nonwhere_filter,
ObRawExpr *&where_filter) ObRawExpr *&where_filter,
ObSelectStmt *temp_table_query)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
bool have_filter = true; bool have_filter = true;
@ -257,6 +283,7 @@ int ObOptimizer::try_push_down_temp_table_filter(ObSqlTempTableInfo &info,
ObSEArray<const ObDMLStmt *, 4> parent_stmts; ObSEArray<const ObDMLStmt *, 4> parent_stmts;
ObSEArray<const ObSelectStmt *, 4> subqueries; ObSEArray<const ObSelectStmt *, 4> subqueries;
ObSEArray<int64_t, 4> table_ids; ObSEArray<int64_t, 4> table_ids;
temp_table_query = (temp_table_query == NULL) ? info.table_query_ : temp_table_query;
for (int64_t i = 0; OB_SUCC(ret) && have_filter && i < info.table_infos_.count(); ++i) { for (int64_t i = 0; OB_SUCC(ret) && have_filter && i < info.table_infos_.count(); ++i) {
TableItem *table = info.table_infos_.at(i).table_item_; TableItem *table = info.table_infos_.at(i).table_item_;
ObDMLStmt *stmt = info.table_infos_.at(i).upper_stmt_; ObDMLStmt *stmt = info.table_infos_.at(i).upper_stmt_;
@ -269,7 +296,7 @@ int ObOptimizer::try_push_down_temp_table_filter(ObSqlTempTableInfo &info,
LOG_WARN("failed to push back", K(ret)); LOG_WARN("failed to push back", K(ret));
} else if (OB_FAIL(parent_stmts.push_back(stmt))) { } else if (OB_FAIL(parent_stmts.push_back(stmt))) {
LOG_WARN("failed to push back", K(ret)); LOG_WARN("failed to push back", K(ret));
} else if (OB_FAIL(subqueries.push_back(table->ref_query_))) { } else if (OB_FAIL(subqueries.push_back(temp_table_query))) {
LOG_WARN("failed to push back", K(ret)); LOG_WARN("failed to push back", K(ret));
} else if (OB_FAIL(table_ids.push_back(table->table_id_))) { } else if (OB_FAIL(table_ids.push_back(table->table_id_))) {
LOG_WARN("failed to push back", K(ret)); LOG_WARN("failed to push back", K(ret));

View File

@ -182,7 +182,8 @@ namespace sql
virtual int optimize(ObDMLStmt &stmt, ObLogPlan *&plan); virtual int optimize(ObDMLStmt &stmt, ObLogPlan *&plan);
virtual int get_optimization_cost(ObDMLStmt &stmt, virtual int get_optimization_cost(ObDMLStmt &stmt,
ObLogPlan *&plan, ObLogPlan *&plan,
double &cost); double &cost,
ObDMLStmt::TempTableInfo *current_temp_table_);
virtual int get_cte_optimization_cost(ObDMLStmt &root_stmt, virtual int get_cte_optimization_cost(ObDMLStmt &root_stmt,
ObSelectStmt *cte_query, ObSelectStmt *cte_query,
ObIArray<ObSelectStmt *> &stmts, ObIArray<ObSelectStmt *> &stmts,
@ -225,7 +226,8 @@ namespace sql
int try_push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info, int try_push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info,
ObRawExpr *&temp_table_filter, ObRawExpr *&temp_table_filter,
ObRawExpr *&where_filter); ObRawExpr *&where_filter,
ObSelectStmt *temp_table_query = NULL);
int push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info, int push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info,
ObRawExpr *&temp_table_filter); ObRawExpr *&temp_table_filter);

View File

@ -412,7 +412,7 @@ int ObTransformRule::evaluate_cost(common::ObIArray<ObParentDMLStmt> &parent_stm
//optctx.set_only_ds_basic_stat(true); //optctx.set_only_ds_basic_stat(true);
ObOptimizer optimizer(optctx); ObOptimizer optimizer(optctx);
ObLogPlan *plan = NULL; ObLogPlan *plan = NULL;
if (OB_FAIL(optimizer.get_optimization_cost(*root_stmt, plan, plan_cost))) { if (OB_FAIL(optimizer.get_optimization_cost(*root_stmt, plan, plan_cost, current_temp_table_))) {
LOG_WARN("failed to get optimization cost", K(ret)); LOG_WARN("failed to get optimization cost", K(ret));
} else if (NULL == check_ctx) { } else if (NULL == check_ctx) {
// do nothing // do nothing
@ -788,6 +788,7 @@ int ObTransformRule::transform_temp_tables(ObIArray<ObParentDMLStmt> &parent_stm
} }
for(int64_t i = 0; OB_SUCC(ret) && i < temp_table_infos.count(); ++i) { for(int64_t i = 0; OB_SUCC(ret) && i < temp_table_infos.count(); ++i) {
ObDMLStmt *child_stmt = temp_table_infos.at(i).temp_table_query_; ObDMLStmt *child_stmt = temp_table_infos.at(i).temp_table_query_;
current_temp_table_ = &temp_table_infos.at(i);
if (OB_ISNULL(child_stmt)) { if (OB_ISNULL(child_stmt)) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
LOG_WARN("null child stmt", K(ret)); LOG_WARN("null child stmt", K(ret));
@ -796,6 +797,7 @@ int ObTransformRule::transform_temp_tables(ObIArray<ObParentDMLStmt> &parent_stm
child_stmt)))) { child_stmt)))) {
LOG_WARN("failed to transform stmt recursively", K(ret)); LOG_WARN("failed to transform stmt recursively", K(ret));
} }
current_temp_table_ = NULL;
//reset ref query //reset ref query
for (int64_t j = 0; OB_SUCC(ret) && j < temp_table_infos.at(i).table_items_.count(); ++j) { for (int64_t j = 0; OB_SUCC(ret) && j < temp_table_infos.at(i).table_items_.count(); ++j) {
TableItem *temp_table = temp_table_infos.at(i).table_items_.at(j); TableItem *temp_table = temp_table_infos.at(i).table_items_.at(j);

View File

@ -274,7 +274,8 @@ public:
transformer_type_(INVALID_TRANSFORM_TYPE), transformer_type_(INVALID_TRANSFORM_TYPE),
trans_happened_(false), trans_happened_(false),
cost_based_trans_tried_(false), cost_based_trans_tried_(false),
stmt_cost_(-1) current_temp_table_(NULL),
stmt_cost_(-1)
{ {
} }
virtual ~ObTransformRule() virtual ~ObTransformRule()
@ -448,6 +449,7 @@ protected:
uint64_t transformer_type_; uint64_t transformer_type_;
bool trans_happened_; bool trans_happened_;
bool cost_based_trans_tried_; bool cost_based_trans_tried_;
ObDMLStmt::TempTableInfo *current_temp_table_;
private: private:
double stmt_cost_; double stmt_cost_;