diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 000f45254..f7a13fbf5 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1566,6 +1566,12 @@ DEF_BOOL(_enable_das_keep_order, OB_TENANT_PARAMETER, "True", DEF_BOOL(_enable_nlj_spf_use_rich_format, OB_TENANT_PARAMETER, "True", "enable nlj and spf use rich format", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_BOOL(_enable_distributed_das_scan, OB_TENANT_PARAMETER, "True", + "enable distributed DAS scan", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_INT(_enable_das_batch_rescan_flag, OB_TENANT_PARAMETER, "0", + "enable das batch rescan for multiple scenarios.", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); DEF_INT(_parallel_max_active_sessions, OB_TENANT_PARAMETER, "0", "[0,]", "max active parallel sessions allowed for tenant. Range: [0,+∞)", diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index a20e48882..be4eb5d2a 100755 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -1572,6 +1572,10 @@ int ObJoinOrder::will_use_das(const uint64_t table_id, LOG_WARN("failed to check hint use das", K(ret)); } else if (create_das_path || create_basic_path) { LOG_TRACE("will use das by hint", K(create_das_path), K(create_basic_path)); + } else if (OB_UNLIKELY(!get_plan()->get_optimizer_context().is_enable_distributed_das_scan())) { + create_das_path = false; + create_basic_path = true; + LOG_TRACE("disable das scan by tenant config", K(create_das_path), K(create_basic_path)); } else if (OB_FAIL(check_opt_rule_use_das(table_id, index_id, index_info_cache, @@ -6875,8 +6879,6 @@ int AccessPath::compute_access_path_batch_rescan() can_batch_rescan = false; } else if (order_direction_ != default_asc_direction() && order_direction_ != ObOrderDirection::UNORDERED) { can_batch_rescan = false; - } else if (plan->get_optimizer_context().enable_experimental_batch_rescan()) { - can_batch_rescan = true; } else if (est_cost_info_.index_meta_info_.is_global_index_ && est_cost_info_.index_meta_info_.is_index_back_ && OB_FAIL(ObOptimizerUtil::get_has_global_index_filters(plan->get_optimizer_context().get_sql_schema_guard(), @@ -6886,8 +6888,8 @@ int AccessPath::compute_access_path_batch_rescan() has_index_lookup_filter))) { LOG_WARN("failed to get has global index filters", K(ret)); } else { - // For the global index lookup, if there is a pushdown filter when scanning the index, batch cannot be used. - can_batch_rescan = !has_index_scan_filter; + // batch rescan when global lookup has index pushdown filter, enabled after 4.2.1.9. + can_batch_rescan = !has_index_scan_filter || plan->get_optimizer_context().enable_global_index_filter_batch(); } if (OB_SUCC(ret)) { @@ -7002,7 +7004,7 @@ int AccessPath::compute_is_das_dynamic_part_pruning(const EqualSets &equal_sets, || OB_ISNULL(table_partition_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected params", K(ret), K(parent_), K(table_partition_info_)); - } else if (!parent_->get_plan()->get_optimizer_context().enable_425_batch_rescan()) { + } else if (!parent_->get_plan()->get_optimizer_context().enable_425_opt_batch_rescan()) { can_das_dynamic_part_pruning_ = false; } else if (table_partition_info_->get_phy_tbl_location_info().get_partition_cnt() <= 1) { can_das_dynamic_part_pruning_ = false; @@ -7964,8 +7966,8 @@ int JoinPath::compute_nlj_batch_rescan() /* join type not support */ } else if (!right_path_->subquery_exprs_.empty()) { /* subplan filter allocated for on condition subquery, not support */ - } else if (IS_SEMI_ANTI_JOIN(join_type_) && !plan->get_optimizer_context().enable_experimental_batch_rescan()) { - /* semi/anti join not support */ + } else if (IS_SEMI_ANTI_JOIN(join_type_) && !plan->get_optimizer_context().enable_semi_anti_join_batch()) { + /* semi/anti join batch, enabled after 4.2.5 */ } else if (OB_FAIL(check_right_has_gi_or_exchange(right_has_gi_or_exchange))) { LOG_WARN("failed to check right has gi or exchange", K(ret)); } else if (right_has_gi_or_exchange) { @@ -7973,20 +7975,22 @@ int JoinPath::compute_nlj_batch_rescan() } else if (right_path_->is_access_path()) { const AccessPath *ap = static_cast(right_path_); can_use_batch_nlj_ = ap->can_batch_rescan_; - if (can_use_batch_nlj_ && !plan->get_optimizer_context().enable_experimental_batch_rescan() - && OB_FAIL(ObOptimizerUtil::check_exec_param_filter_exprs(ap->est_cost_info_.pushdown_prefix_filters_, - right_path_->nl_params_, - can_use_batch_nlj_))) { - LOG_WARN("failed to check exec param filter exprs", K(ret)); + if (can_use_batch_nlj_ && !plan->get_optimizer_context().enable_non_prefix_exec_param_batch()) { + if (OB_FAIL(ObOptimizerUtil::check_exec_param_filter_exprs(ap->est_cost_info_.pushdown_prefix_filters_, + right_path_->nl_params_, + can_use_batch_nlj_))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); + } } } else if (!right_path_->is_subquery_path()) { /* do nothing, only access_path and subquery_path may use batch nlj */ - } else if (plan->get_optimizer_context().enable_experimental_batch_rescan() && + } else if (plan->get_optimizer_context().enable_425_exec_batch_rescan() && OB_FAIL(ObOptimizerUtil::check_can_batch_rescan(static_cast(right_path_)->root_, - false, + right_path_->nl_params_, + true, can_use_batch_nlj_))) { LOG_WARN("failed to check plan can batch rescan", K(ret)); - } else if (!plan->get_optimizer_context().enable_experimental_batch_rescan() && + } else if (!plan->get_optimizer_context().enable_425_exec_batch_rescan() && OB_FAIL(ObOptimizerUtil::check_can_batch_rescan_compat(static_cast(right_path_)->root_, right_path_->nl_params_, true, diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index bc65568d2..5de30734e 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -2554,7 +2554,7 @@ int ObLogPlan::init_rescan_info_for_query_ref(const ObLogPlan &parent_plan, is_rescan_subplan_ = parent_plan.is_rescan_subplan_ || is_rescan_subquery; disable_child_batch_rescan_ = parent_plan.disable_child_batch_rescan_ || (is_rescan_subquery - && !get_optimizer_context().enable_experimental_batch_rescan()); + && !get_optimizer_context().enable_spf_semi_anti_child_batch()); return ret; } @@ -2566,7 +2566,7 @@ int ObLogPlan::init_rescan_info_for_subquery_paths(const ObLogPlan &parent_plan, is_rescan_subplan_ = parent_plan.is_rescan_subplan_ || is_inner_path; disable_child_batch_rescan_ = parent_plan.disable_child_batch_rescan_ || (is_semi_anti_join_inner_path - && !get_optimizer_context().enable_experimental_batch_rescan()); + && !get_optimizer_context().enable_spf_semi_anti_child_batch()); return ret; } diff --git a/src/sql/optimizer/ob_log_subplan_filter.cpp b/src/sql/optimizer/ob_log_subplan_filter.cpp index 6cc06fd30..80c1be7d0 100755 --- a/src/sql/optimizer/ob_log_subplan_filter.cpp +++ b/src/sql/optimizer/ob_log_subplan_filter.cpp @@ -462,10 +462,10 @@ int ObLogSubPlanFilter::compute_spf_batch_rescan() /* subplan filter group rescan is disabled */ } else if (get_plan()->get_disable_child_batch_rescan()) { /* do nothing */ - } else if (get_plan()->get_optimizer_context().enable_experimental_batch_rescan() + } else if (get_plan()->get_optimizer_context().enable_425_exec_batch_rescan() && OB_FAIL(compute_spf_batch_rescan(can_batch))) { LOG_WARN("failed to compute group rescan", K(ret)); - } else if (!get_plan()->get_optimizer_context().enable_experimental_batch_rescan() + } else if (!get_plan()->get_optimizer_context().enable_425_exec_batch_rescan() && OB_FAIL(compute_spf_batch_rescan_compat(can_batch))) { LOG_WARN("failed to compute group rescan compat", K(ret)); } else { @@ -482,19 +482,34 @@ int ObLogSubPlanFilter::compute_spf_batch_rescan(bool &can_batch) const ObShardingInfo *sharding = NULL; const ObLogicalOperator *child = NULL; const ObDMLStmt *stmt = NULL; + const ObLogPlan *plan = NULL; bool has_ref_assign_user_var = false; bool left_allocated_exchange = false; bool right_allocated_exchange = false; bool has_rescan_subquery = false; - // check if exec params contain rownum + if (OB_ISNULL(plan = get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(plan)); + } else if ((!init_plan_idxs_.is_empty() || !one_time_idxs_.is_empty()) && + !plan->get_optimizer_context().enable_onetime_initplan_batch()) { + /* spf contains onetime expr or init plan, enabled after 4.2.5 */ + can_batch = false; + } + + // check if exec params contain sub_query/rownum for (int64_t i = 0; OB_SUCC(ret) && can_batch && i < exec_params_.count(); i++) { if (OB_ISNULL(exec_params_.at(i)) || OB_ISNULL(ref_expr = exec_params_.at(i)->get_ref_expr())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(i), K(ref_expr), KPC(exec_params_.at(i))); } else { - can_batch = !ref_expr->has_flag(CNT_ROWNUM); + can_batch &= !ref_expr->has_flag(CNT_ROWNUM); + if (can_batch && !plan->get_optimizer_context().enable_contains_subquery_batch()) { + can_batch &= !ref_expr->has_flag(CNT_SUB_QUERY); + } } } + + // check if child can batch rescan for (int64_t i = 0; OB_SUCC(ret) && can_batch && i < get_num_of_child(); i++) { if (OB_ISNULL(child = get_child(i)) || OB_ISNULL(sharding = child->get_sharding()) || OB_ISNULL(stmt= child->get_stmt())) { @@ -504,7 +519,7 @@ int ObLogSubPlanFilter::compute_spf_batch_rescan(bool &can_batch) left_allocated_exchange = child->is_exchange_allocated(); } else if (init_plan_idxs_.has_member(i) || one_time_idxs_.has_member(i)) { can_batch = sharding->is_single(); - } else if (OB_FAIL(ObOptimizerUtil::check_can_batch_rescan(child, true, can_batch))) { + } else if (OB_FAIL(ObOptimizerUtil::check_can_batch_rescan(child, exec_params_, false, can_batch))) { LOG_WARN("failed to check plan can batch rescan", K(ret)); } else if (OB_FAIL(stmt->has_ref_assign_user_var(has_ref_assign_user_var))) { LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); diff --git a/src/sql/optimizer/ob_opt_est_cost_model.cpp b/src/sql/optimizer/ob_opt_est_cost_model.cpp index 5863baf2a..620663da2 100644 --- a/src/sql/optimizer/ob_opt_est_cost_model.cpp +++ b/src/sql/optimizer/ob_opt_est_cost_model.cpp @@ -1694,7 +1694,7 @@ int ObOptEstCostModel::calc_das_rpc_cost(const ObCostTableScanInfo &est_cost_inf if (OB_ISNULL(est_cost_info.sel_ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(est_cost_info.sel_ctx_)); - } else if (!est_cost_info.sel_ctx_->get_opt_ctx().enable_425_batch_rescan()) { + } else if (!est_cost_info.sel_ctx_->get_opt_ctx().enable_425_opt_batch_rescan()) { /* do nothing */ } else if (!est_cost_info.is_das_scan_ || !est_cost_info.is_rescan_) { /* do nothing */ diff --git a/src/sql/optimizer/ob_optimizer.cpp b/src/sql/optimizer/ob_optimizer.cpp index 2c48132b7..e928c2c71 100644 --- a/src/sql/optimizer/ob_optimizer.cpp +++ b/src/sql/optimizer/ob_optimizer.cpp @@ -702,6 +702,8 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession bool better_inlist_costing = false; bool enable_spf_batch_rescan = session.is_spf_mlj_group_rescan_enabled(); bool enable_px_ordered_coord = GCONF._enable_px_ordered_coord; + int64_t das_batch_rescan_flag = tenant_config.is_valid() ? tenant_config->_enable_das_batch_rescan_flag : 0; + bool enable_distributed_das_scan = tenant_config.is_valid() ? tenant_config->_enable_distributed_das_scan : true; const ObOptParamHint &opt_params = ctx_.get_global_hint().opt_params_; if (OB_ISNULL(query_ctx)) { ret = OB_ERR_UNEXPECTED; @@ -760,9 +762,11 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession LOG_WARN("failed to check partition wise plan enabled", K(ret)); } else if (OB_FAIL(opt_params.get_bool_opt_param(ObOptParamHint::ENABLE_PX_ORDERED_COORD, enable_px_ordered_coord))) { LOG_WARN("failed to get opt param enable px ordered coord", K(ret)); + } else if (OB_FAIL(opt_params.get_integer_opt_param(ObOptParamHint::DAS_BATCH_RESCAN_FLAG, das_batch_rescan_flag))) { + LOG_WARN("failed to get das batch rescan flag", K(ret)); } else { ctx_.init_batch_rescan_flags(enable_use_batch_nlj, enable_spf_batch_rescan, - query_ctx->optimizer_features_enable_version_); + query_ctx->optimizer_features_enable_version_, das_batch_rescan_flag); ctx_.set_storage_estimation_enabled(storage_estimation_enabled); ctx_.set_serial_set_order(force_serial_set_order); ctx_.set_has_multiple_link_stmt(link_stmt_count > 1); @@ -778,6 +782,7 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession ctx_.set_enable_better_inlist_costing(better_inlist_costing); ctx_.set_push_join_pred_into_view_enabled(push_join_pred_into_view_enabled); ctx_.set_enable_px_ordered_coord(enable_px_ordered_coord); + ctx_.set_enable_distributed_das_scan(enable_distributed_das_scan); if (!hash_join_enabled && !optimizer_sortmerge_join_enabled && !nested_loop_join_enabled) { diff --git a/src/sql/optimizer/ob_optimizer_context.h b/src/sql/optimizer/ob_optimizer_context.h index 284026fef..e9a6055e9 100644 --- a/src/sql/optimizer/ob_optimizer_context.h +++ b/src/sql/optimizer/ob_optimizer_context.h @@ -271,7 +271,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, enable_new_query_range_(false), partition_wise_plan_enabled_(true), enable_px_ordered_coord_(false), - enable_opt_row_goal_(ObEnableOptRowGoal::MAX) + enable_opt_row_goal_(ObEnableOptRowGoal::MAX), + enable_distributed_das_scan_(true) { } inline common::ObOptStatManager *get_opt_stat_manager() { return opt_stat_manager_; } inline void set_opt_stat_manager(common::ObOptStatManager *sm) { opt_stat_manager_ = sm; } @@ -437,20 +438,80 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, return enable_px_batch_rescan_; } + static const int BATCH_RESCAN_BIT_GLOBAL_INDEX_FILTER = 0; + static const int BATCH_RESCAN_BIT_SPF_SEMI_ANTI_LEFT_CHILD = 1; + static const int BATCH_RESCAN_BIT_SPF_SEMI_ANTI_CHILD = 2; + static const int BATCH_RESCAN_BIT_SEMI_ANTI_JOIN = 3; + static const int BATCH_RESCAN_BIT_LIMIT_PUSHDOWN = 4; + static const int BATCH_RESCAN_BIT_NON_PREFIX_EXEC_PARAM = 5; + static const int BATCH_RESCAN_BIT_NORMAL_SCAN = 6; + static const int BATCH_RESCAN_BIT_ONETIME_INITPLAN = 7; + static const int BATCH_RESCAN_BIT_CONTAINS_SUBQUERY = 8; + static const int BATCH_RESCAN_BIT_NON_BASIC_SCAN = 9; + static const int BATCH_RESCAN_BIT_STARTUP_FILTER = 10; + + // whether batch rescan can be enabled depends on two factors: + // 1. current version must support corresponding batch rescan scenario + // 2. corresponding batch rescan configuration must be enabled void init_batch_rescan_flags(const bool enable_batch_nlj, const bool enable_batch_spf, - const uint64_t opt_version) + const uint64_t opt_version, + const int64_t batch_rescan_flag) { enable_nlj_batch_rescan_ = enable_batch_nlj; enable_spf_batch_rescan_ = enable_batch_nlj && enable_batch_spf; - // adaptive group-rescan is supported in 4.2.3.0 - enable_425_batch_rescan_ = GET_MIN_CLUSTER_VERSION() >= COMPAT_VERSION_4_2_3 - && (opt_version >= COMPAT_VERSION_4_2_5 || opt_version >= COMPAT_VERSION_4_3_5); + bool enable_425_opt_version = false; + if (get_query_ctx() != nullptr) { + enable_425_opt_version = get_query_ctx()->check_opt_compat_version( + COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5); + } + enable_425_opt_batch_rescan_ = enable_425_opt_version; + enable_global_index_filter_ = opt_version > COMPAT_VERSION_4_2_1_BP8 && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_GLOBAL_INDEX_FILTER)); + enable_spf_semi_anti_left_child_ = opt_version > COMPAT_VERSION_4_2_1_BP8 && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_SPF_SEMI_ANTI_LEFT_CHILD)); + enable_spf_semi_anti_child_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_SPF_SEMI_ANTI_CHILD)); + enable_semi_anti_join_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_SEMI_ANTI_JOIN)); + enable_limit_pushdown_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_LIMIT_PUSHDOWN)); + enable_non_prefix_exec_param_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_NON_PREFIX_EXEC_PARAM)); + enable_normal_scan_ = enable_425_opt_version&& + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_NORMAL_SCAN)); + enable_onetime_initplan_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_ONETIME_INITPLAN)); + enable_contains_subquery_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_CONTAINS_SUBQUERY)); + enable_non_basic_scan_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_NON_BASIC_SCAN)); + enable_startup_filter_ = enable_425_opt_version && + (batch_rescan_flag & (0x1L << BATCH_RESCAN_BIT_STARTUP_FILTER)); + // when enable das batch rescan flag and opt_version >= 4.2.5, use new interface to check can batch rescan, + // otherwise, use old interface to check can batch rescan for compatibility. + enable_425_exec_batch_rescan_ = (batch_rescan_flag != 0) && enable_425_opt_version; + // when use tracepoint, enable all batch rescan. + if ((OB_E(EventTable::EN_DAS_GROUP_RESCAN_TEST_MODE) OB_SUCCESS) != OB_SUCCESS) { + batch_rescan_flags_ = INT64_MAX; + } } + inline bool enable_nlj_batch_rescan() const { return enable_nlj_batch_rescan_; } inline bool enable_spf_batch_rescan() const { return enable_spf_batch_rescan_; } - inline bool enable_425_batch_rescan() const { return enable_425_batch_rescan_; } - inline bool enable_experimental_batch_rescan() const { return (OB_E(EventTable::EN_DAS_GROUP_RESCAN_TEST_MODE) OB_SUCCESS) != OB_SUCCESS; } + inline bool enable_425_opt_batch_rescan() const { return enable_425_opt_batch_rescan_; } + inline bool enable_425_exec_batch_rescan() const { return enable_425_exec_batch_rescan_; } + inline bool enable_global_index_filter_batch() const { return enable_global_index_filter_; } + inline bool enable_spf_semi_anti_left_child_batch() const { return enable_spf_semi_anti_left_child_; } + inline bool enable_spf_semi_anti_child_batch() const { return enable_spf_semi_anti_child_; } + inline bool enable_semi_anti_join_batch() const { return enable_semi_anti_join_; } + inline bool enable_limit_pushdown_batch() const { return enable_limit_pushdown_; } + inline bool enable_non_prefix_exec_param_batch() const { return enable_non_prefix_exec_param_; } + inline bool enable_normal_scan_batch() const { return enable_normal_scan_; } + inline bool enable_onetime_initplan_batch() const { return enable_onetime_initplan_; } + inline bool enable_contains_subquery_batch() const { return enable_contains_subquery_; } + inline bool enable_non_basic_scan_batch() const { return enable_non_basic_scan_; } + inline bool enable_startup_filter_batch() const { return enable_startup_filter_; } int get_px_object_sample_rate() { @@ -700,6 +761,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, inline bool enable_new_query_range() const { return enable_new_query_range_; } inline void set_enable_opt_row_goal(int64_t type) { enable_opt_row_goal_ = static_cast(type); } inline ObEnableOptRowGoal get_enable_opt_row_goal() const { return enable_opt_row_goal_; } + inline bool is_enable_distributed_das_scan() const { return enable_distributed_das_scan_; } + inline void set_enable_distributed_das_scan(bool enabled) { enable_distributed_das_scan_ = enabled; } private: ObSQLSessionInfo *session_info_; ObExecContext *exec_ctx_; @@ -740,9 +803,21 @@ private: union { int64_t batch_rescan_flags_; struct { - int64_t enable_nlj_batch_rescan_ : 1; // enable nestloop inner path batch rescan - int64_t enable_spf_batch_rescan_ : 1; // enable subplan filter batch rescan - int64_t enable_425_batch_rescan_ : 1; // enbale batch rescan behaviors supported in 4.2.5 + int64_t enable_nlj_batch_rescan_ : 1; // enable nestloop inner path batch rescan + int64_t enable_spf_batch_rescan_ : 1; // enable subplan filter batch rescan + int64_t enable_425_opt_batch_rescan_ : 1; // enable optimizer batch rescan behaviors supported in 4.2.5 + int64_t enable_425_exec_batch_rescan_ : 1; // enable exec batch rescan behaviors supported in 4.2.5 + int64_t enable_global_index_filter_ : 1; // enable batch rescan when has global index filter + int64_t enable_spf_semi_anti_left_child_ : 1; // enable batch rescan when as spf/semi-anti join left child + int64_t enable_spf_semi_anti_child_ : 1; // enable batch rescan when as spf/semi-anti join child + int64_t enable_semi_anti_join_ : 1; // enable semi/anti join batch rescan + int64_t enable_limit_pushdown_ : 1; // enable batch rescan when contains limit pushdown + int64_t enable_non_prefix_exec_param_ : 1; // enable batch rescan when no prefix exec param + int64_t enable_normal_scan_ : 1; // enable batch rescan when use normal table scan + int64_t enable_onetime_initplan_ : 1; // enable batch rescan when contains onetime init plan + int64_t enable_contains_subquery_ : 1; // enable batch rescan when exec param contains subquery + int64_t enable_non_basic_scan_ : 1; // enable batch rescan when not basic table scan/subplan scan + int64_t enable_startup_filter_ : 1; // enable batch rescan when startup filter contains exec param }; }; common::ObSEArray column_usage_infos_; @@ -807,6 +882,7 @@ private: bool partition_wise_plan_enabled_; bool enable_px_ordered_coord_; ObEnableOptRowGoal enable_opt_row_goal_; + bool enable_distributed_das_scan_; }; } } diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index 87e58a898..266840844 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -10295,27 +10295,67 @@ int ObOptimizerUtil::get_has_global_index_filters(const ObIArray &fi return ret; } -// check batch rescan for nlj / subplan filter +// check batch rescan for nlj / subplan filter int ObOptimizerUtil::check_can_batch_rescan(const ObLogicalOperator *op, - const bool allow_normal_scan, + const ObIArray &rescan_params, + bool for_nlj, bool &can_batch_rescan) { int ret = OB_SUCCESS; can_batch_rescan = false; - if (OB_ISNULL(op)) { + bool has_exec_param = false; + const ObLogPlan *plan = nullptr; + if (OB_ISNULL(op) || OB_ISNULL(plan = op->get_plan())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(op)); + LOG_WARN("get unexpected null", K(ret), K(op), K(plan)); + } else if (OB_FAIL(check_exec_param_filter_exprs(op->get_startup_exprs(), has_exec_param))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); + } else if (has_exec_param && !plan->get_optimizer_context().enable_startup_filter_batch()) { + /* startup filter contains exec param, enabled after 4.2.5 */ + } else if ((log_op_def::LOG_LIMIT == op->get_type() + || (op->is_table_scan() && NULL != static_cast(op)->get_limit_expr())) + && !plan->get_optimizer_context().enable_limit_pushdown_batch()) { + /* contains limit pushdown, enabled after 4.2.5 */ } else if (op->is_table_scan()) { const ObLogTableScan *table_scan = static_cast(op); - can_batch_rescan = (allow_normal_scan || table_scan->use_das()) && table_scan->can_batch_rescan(); - } else if (1 == op->get_num_of_child() || log_op_def::LOG_SET == op->get_type()) { - can_batch_rescan = true; - for (int64_t i = 0; OB_SUCC(ret) && can_batch_rescan && i < op->get_num_of_child(); ++i) { - if (OB_FAIL(SMART_CALL(check_can_batch_rescan(op->get_child(i), false, can_batch_rescan)))) { - LOG_WARN("failed to check batch nlj", K(ret)); + if (OB_ISNULL(table_scan->get_est_cost_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null est cost info", K(ret)); + } else if (!table_scan->can_batch_rescan()) { + can_batch_rescan = false; + } else if (!table_scan->use_das() && !plan->get_optimizer_context().enable_normal_scan_batch()) { + /* normal table scan, enabled after 4.2.5 */ + can_batch_rescan = false; + } else if (!plan->get_optimizer_context().enable_non_prefix_exec_param_batch()) { + if (OB_FAIL(check_exec_param_filter_exprs(table_scan->get_est_cost_info()->pushdown_prefix_filters_, + rescan_params, + can_batch_rescan))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); } + } else { + can_batch_rescan = true; } - } else { // other multi child op use batch is disabled, multi level nlj use batch is disabled + } else if (log_op_def::LOG_SUBPLAN_SCAN == op->get_type()) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan(op->get_child(0), rescan_params, for_nlj, can_batch_rescan)))) { + LOG_WARN("failed to check can batch rescan for op child", K(ret)); + } + } else if (!for_nlj && !plan->get_optimizer_context().enable_non_basic_scan_batch()) { + /* non table scan/subplan scan for subplan filter, enabled after 4.2.5 */ + } else if (1 == op->get_num_of_child()) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan(op->get_child(0), rescan_params, for_nlj, can_batch_rescan)))) { + LOG_WARN("failed to check can batch rescan for op child", K(ret)); + } + } else if (log_op_def::LOG_SET == op->get_type()) { + can_batch_rescan = ObSelectStmt::UNION == static_cast(op)->get_set_op() + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_5_0; + for (int64_t i = 0; OB_SUCC(ret) && can_batch_rescan && i < op->get_num_of_child(); ++i) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan(op->get_child(i), rescan_params, for_nlj, can_batch_rescan)))) { + LOG_WARN("failed to check batch rescan", K(ret)); + } else {/* do nothing */} + } + } else { + // other multi child op use batch is disabled + // multi level nlj use batch is disabled can_batch_rescan = false; } return ret; diff --git a/src/sql/optimizer/ob_optimizer_util.h b/src/sql/optimizer/ob_optimizer_util.h index 053a1cb9b..e73155c26 100644 --- a/src/sql/optimizer/ob_optimizer_util.h +++ b/src/sql/optimizer/ob_optimizer_util.h @@ -1633,10 +1633,11 @@ public: const ObIArray &index_columns, bool &has_index_scan_filter, bool &has_index_lookup_filter); + static int check_can_batch_rescan(const ObLogicalOperator *op, - const bool allow_normal_scan, + const ObIArray &rescan_params, + bool for_nlj, bool &can_batch_rescan); - static int check_can_batch_rescan_compat(const AccessPath &access_path, bool &can_batch_rescan); static int check_can_batch_rescan_compat(ObLogicalOperator *op, const ObIArray &rescan_params, bool for_nlj, diff --git a/src/sql/plan_cache/ob_plan_cache_util.cpp b/src/sql/plan_cache/ob_plan_cache_util.cpp index 33d11aaa3..cfeea4c42 100644 --- a/src/sql/plan_cache/ob_plan_cache_util.cpp +++ b/src/sql/plan_cache/ob_plan_cache_util.cpp @@ -550,6 +550,8 @@ int ObConfigInfoInPC::load_influence_plan_config() 0 : (tenant_config->_use_hash_rollup.case_compare("forced") == 0 ? 1 : 2); enable_nlj_spf_use_rich_format_ = tenant_config->_enable_nlj_spf_use_rich_format; + enable_distributed_das_scan_ = tenant_config->_enable_distributed_das_scan; + enable_das_batch_rescan_flag_ = tenant_config->_enable_das_batch_rescan_flag; } return ret; @@ -628,6 +630,12 @@ int ObConfigInfoInPC::serialize_configs(char *buf, int buf_len, int64_t &pos) } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, "%d,", enable_nlj_spf_use_rich_format_))) { SQL_PC_LOG(WARN, "failed to databuff_printf", K(ret), K(enable_nlj_spf_use_rich_format_)); + } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, + "%d,", enable_distributed_das_scan_))) { + SQL_PC_LOG(WARN, "failed to databuff_printf", K(ret), K(enable_distributed_das_scan_)); + } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, + "%ld,", enable_das_batch_rescan_flag_))) { + SQL_PC_LOG(WARN, "failed to databuff_printf", K(ret), K(enable_das_batch_rescan_flag_)); } else { // do nothing } diff --git a/src/sql/plan_cache/ob_plan_cache_util.h b/src/sql/plan_cache/ob_plan_cache_util.h index 77143a3f3..295787049 100644 --- a/src/sql/plan_cache/ob_plan_cache_util.h +++ b/src/sql/plan_cache/ob_plan_cache_util.h @@ -1041,6 +1041,8 @@ public: min_cluster_version_(0), is_enable_px_fast_reclaim_(false), enable_spf_batch_rescan_(false), + enable_distributed_das_scan_(false), + enable_das_batch_rescan_flag_(0), enable_var_assign_use_das_(false), enable_das_keep_order_(false), enable_nlj_spf_use_rich_format_(false), @@ -1093,6 +1095,8 @@ public: uint64_t min_cluster_version_; bool is_enable_px_fast_reclaim_; bool enable_spf_batch_rescan_; + bool enable_distributed_das_scan_; + int64_t enable_das_batch_rescan_flag_; bool enable_var_assign_use_das_; bool enable_das_keep_order_; bool enable_nlj_spf_use_rich_format_; diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index d33827e06..790711628 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -985,6 +985,10 @@ bool ObOptParamHint::is_param_val_valid(const OptParamType param_type, const ObO } break; } + case DAS_BATCH_RESCAN_FLAG: { + is_valid = val.is_int() && 0 <= val.get_int(); + break; + } default: LOG_TRACE("invalid opt param val", K(param_type), K(val)); break; diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 1d1fab1d4..7de467f2c 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -202,6 +202,7 @@ struct ObOptParamHint DEF(LOB_ROWSETS_MAX_ROWS,) \ DEF(ENABLE_ENUM_SET_SUBSCHEMA,) \ DEF(ENABLE_OPTIMIZER_ROWGOAL,) \ + DEF(DAS_BATCH_RESCAN_FLAG,) \ DECLARE_ENUM(OptParamType, opt_param, OPT_PARAM_TYPE_DEF, static); diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 397a1ea47..c5edf972c 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -336,12 +336,14 @@ _enable_column_store _enable_compaction_diagnose _enable_compatible_monotonic _enable_convert_real_to_decimal +_enable_das_batch_rescan_flag _enable_das_keep_order _enable_dblink_reuse_connection _enable_dbms_job_package _enable_dbms_lob_partial_update _enable_decimal_int_type _enable_defensive_check +_enable_distributed_das_scan _enable_drop_and_add_index _enable_easy_keepalive _enable_enhanced_cursor_validation