push cte preds when generate plan in cost based rewrite
This commit is contained in:
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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_;
|
||||||
|
Reference in New Issue
Block a user