allocate material when more than one link scan exist
This commit is contained in:
@ -294,6 +294,8 @@ int ObLinkScanOp::inner_get_next_row()
|
||||
} else if (OB_FAIL(result_->next())) {
|
||||
if (OB_ITER_END != ret) {
|
||||
LOG_WARN("failed to get next row", K(ret));
|
||||
} else {
|
||||
reset_result();
|
||||
}
|
||||
} else {
|
||||
const ObIArray<ObExpr *> &output = spec_.output_;
|
||||
@ -358,6 +360,7 @@ int ObLinkScanOp::inner_get_next_batch(const int64_t max_row_cnt)
|
||||
if (iter_end_) {
|
||||
brs_.size_ = 0;
|
||||
brs_.end_ = true;
|
||||
reset_result();
|
||||
} else {
|
||||
ObEvalCtx::BatchInfoScopeGuard batch_info_guard(eval_ctx_);
|
||||
auto loop_cnt = common::min(max_row_cnt, MY_SPEC.max_batch_size_);
|
||||
|
||||
@ -22,8 +22,14 @@ ObLogLinkScan::ObLogLinkScan(ObLogPlan &plan)
|
||||
int ObLogLinkScan::allocate_expr_post(ObAllocExprContext &ctx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < output_exprs_.count(); ++i) {
|
||||
ObRawExpr *expr = output_exprs_.at(i);
|
||||
const ObSelectStmt *stmt = NULL;
|
||||
if (OB_ISNULL(get_plan()) ||
|
||||
OB_ISNULL(stmt = static_cast<const ObSelectStmt *>(get_plan()->get_stmt()))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(stmt), K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_select_item_size(); ++i) {
|
||||
ObRawExpr *expr = stmt->get_select_item(i).expr_;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("null expr", K(ret));
|
||||
|
||||
@ -622,6 +622,7 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt)
|
||||
int64_t max_table_hint = 1;
|
||||
ObDMLStmt *target_stmt = &stmt;
|
||||
ObSQLSessionInfo *session = ctx_.get_session_info();
|
||||
int64_t link_stmt_count = 0;
|
||||
if (OB_ISNULL(target_stmt) || OB_ISNULL(session)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
@ -645,7 +646,10 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt)
|
||||
session_enable_parallel,
|
||||
session_force_parallel_dop))) {
|
||||
LOG_WARN("failed to get session parallel info", K(ret));
|
||||
} else if (OB_FAIL(calc_link_stmt_count(*target_stmt, link_stmt_count))) {
|
||||
LOG_WARN("calc link stmt count failed", K(ret));
|
||||
} else {
|
||||
ctx_.set_has_multiple_link_stmt(link_stmt_count > 1);
|
||||
parallel = ctx_.get_global_hint().get_parallel_hint();
|
||||
if (parallel <= 0) {
|
||||
parallel = ObGlobalHint::DEFAULT_PARALLEL;
|
||||
@ -794,6 +798,45 @@ int ObOptimizer::check_whether_contain_nested_sql(const ObDMLStmt &stmt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizer::calc_link_stmt_count(const ObDMLStmt &stmt, int64_t &count)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (stmt.is_dblink_stmt()) {
|
||||
count += 1;
|
||||
} else {
|
||||
ObSEArray<ObSelectStmt *, 4> child_stmts;
|
||||
if (OB_FAIL(stmt.get_child_stmts(child_stmts))) {
|
||||
LOG_WARN("failed to get child stmts", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
|
||||
if (OB_ISNULL(child_stmts.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(SMART_CALL(calc_link_stmt_count(*child_stmts.at(i), count)))) {
|
||||
LOG_WARN("failed to extract column usage info", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
const common::ObIArray<TableItem*> &table_items = stmt.get_table_items();
|
||||
for (int64_t i = 0; i < table_items.count() && OB_SUCC(ret); i++) {
|
||||
const TableItem *table_item = table_items.at(i);
|
||||
if (OB_ISNULL(table_item)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get null ptr", K(ret));
|
||||
} else if (table_item->is_temp_table()) {
|
||||
if (OB_ISNULL(table_item->ref_query_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get null ptr", K(ret));
|
||||
} else if (OB_FAIL(SMART_CALL(calc_link_stmt_count(*table_item->ref_query_, count)))) {
|
||||
LOG_WARN("failed to extract column usage info", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizer::extract_column_usage_info(const ObDMLStmt &stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
@ -215,6 +215,7 @@ namespace sql
|
||||
const ObColumnRefRawExpr &column_expr,
|
||||
int64_t flag);
|
||||
int check_whether_contain_nested_sql(const ObDMLStmt &stmt);
|
||||
int calc_link_stmt_count(const ObDMLStmt &stmt, int64_t &count);
|
||||
private:
|
||||
ObOptimizerContext &ctx_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ObOptimizer);
|
||||
|
||||
@ -148,7 +148,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
|
||||
nested_sql_flags_(0),
|
||||
has_for_update_(false),
|
||||
has_var_assign_(false),
|
||||
is_var_assign_only_in_root_stmt_(false)
|
||||
is_var_assign_only_in_root_stmt_(false),
|
||||
has_multiple_link_stmt_(false)
|
||||
{ }
|
||||
inline common::ObOptStatManager *get_opt_stat_manager() { return opt_stat_manager_; }
|
||||
inline void set_opt_stat_manager(common::ObOptStatManager *sm) { opt_stat_manager_ = sm; }
|
||||
@ -474,6 +475,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
|
||||
inline void set_has_var_assign(bool v) { has_var_assign_ = v; }
|
||||
inline bool is_var_assign_only_in_root_stmt() { return is_var_assign_only_in_root_stmt_; }
|
||||
inline void set_is_var_assign_only_in_root_stmt(bool v) { is_var_assign_only_in_root_stmt_ = v; }
|
||||
inline bool has_multiple_link_stmt() const { return has_multiple_link_stmt_; }
|
||||
inline void set_has_multiple_link_stmt(bool v) { has_multiple_link_stmt_ = v; }
|
||||
|
||||
private:
|
||||
ObSQLSessionInfo *session_info_;
|
||||
@ -545,6 +548,7 @@ private:
|
||||
bool has_for_update_;
|
||||
bool has_var_assign_;
|
||||
bool is_var_assign_only_in_root_stmt_;
|
||||
bool has_multiple_link_stmt_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -3993,16 +3993,26 @@ int ObSelectLogPlan::generate_dblink_raw_plan()
|
||||
//do nothing
|
||||
} else if (OB_FAIL(allocate_link_scan_as_top(top))) {
|
||||
LOG_WARN("failed to allocate link dml as top", K(ret));
|
||||
} else {
|
||||
top->set_dblink_id(dblink_id);
|
||||
ObLogLinkScan *link_scan = static_cast<ObLogLinkScan *>(top);
|
||||
if (OB_FAIL(link_scan->set_link_stmt(stmt))) {
|
||||
LOG_WARN("failed to set link stmt", K(ret));
|
||||
} else if (0 == dblink_id) {
|
||||
link_scan->set_reverse_link(true);
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
// do nothing
|
||||
} else if (optimizer_context_.has_multiple_link_stmt()
|
||||
&& OB_FAIL(allocate_material_as_top(top))) {
|
||||
LOG_WARN("allocate material above link scan failed", K(ret));
|
||||
} else if (OB_FAIL(make_candidate_plans(top))) {
|
||||
LOG_WARN("failed to make candidate plans", K(ret));
|
||||
} else if (OB_FAIL(static_cast<ObLogLink *>(top)->set_link_stmt(stmt))) {
|
||||
LOG_WARN("failed to set link stmt", K(ret));
|
||||
} else {
|
||||
top->mark_is_plan_root();
|
||||
top->get_plan()->set_plan_root(top);
|
||||
top->set_dblink_id(dblink_id);
|
||||
if (0 == dblink_id) {
|
||||
static_cast<ObLogLinkScan *>(top)->set_reverse_link(true);
|
||||
// reset dblink info, to avoid affecting the next execution flow
|
||||
query_ctx->get_query_hint_for_update().get_global_hint().reset_dblink_info_hint();
|
||||
} else {
|
||||
|
||||
@ -970,6 +970,7 @@ public:
|
||||
int add_autoinc_param(share::AutoincParam &autoinc_param) { return autoinc_params_.push_back(autoinc_param); }
|
||||
inline void set_dblink_id(int64_t id) { dblink_id_ = id; }
|
||||
inline int64_t get_dblink_id() const { return dblink_id_; }
|
||||
inline bool is_dblink_stmt() const { return OB_INVALID_ID != dblink_id_; }
|
||||
inline void set_reverse_link() { is_reverse_link_ = true; }
|
||||
inline bool is_reverse_link() const { return is_reverse_link_; }
|
||||
int add_subquery_ref(ObQueryRefRawExpr *query_ref);
|
||||
|
||||
Reference in New Issue
Block a user