diff --git a/src/share/system_variable/ob_sys_var_class_type.h b/src/share/system_variable/ob_sys_var_class_type.h index 2da8beef9..ab02de4e7 100644 --- a/src/share/system_variable/ob_sys_var_class_type.h +++ b/src/share/system_variable/ob_sys_var_class_type.h @@ -634,6 +634,7 @@ enum ObSysVarClassType SYS_VAR_RANGE_INDEX_DIVE_LIMIT = 10740, SYS_VAR_PARTITION_INDEX_DIVE_LIMIT = 10741, SYS_VAR_OB_TABLE_ACCESS_POLICY = 10742, + SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL = 10747, }; } diff --git a/src/share/system_variable/ob_system_variable_alias.h b/src/share/system_variable/ob_system_variable_alias.h index a8fbe7da7..104215e4e 100644 --- a/src/share/system_variable/ob_system_variable_alias.h +++ b/src/share/system_variable/ob_system_variable_alias.h @@ -629,6 +629,7 @@ namespace share static const char* const OB_SV_RANGE_INDEX_DIVE_LIMIT = "range_index_dive_limit"; static const char* const OB_SV_PARTITION_INDEX_DIVE_LIMIT = "partition_index_dive_limit"; static const char* const OB_SV_TABLE_ACCESS_POLICY = "ob_table_access_policy"; + static const char* const OB_SV_ENABLE_OPTIMIZER_ROWGOAL = "enable_optimizer_rowgoal"; } } diff --git a/src/share/system_variable/ob_system_variable_factory.cpp b/src/share/system_variable/ob_system_variable_factory.cpp index ab04741b4..de96c8cc5 100644 --- a/src/share/system_variable/ob_system_variable_factory.cpp +++ b/src/share/system_variable/ob_system_variable_factory.cpp @@ -514,6 +514,12 @@ const char *ObSysVarObTableAccessPolicy::OB_TABLE_ACCESS_POLICY_NAMES[] = { "AUTO", 0 }; +const char *ObSysVarEnableOptimizerRowgoal::ENABLE_OPTIMIZER_ROWGOAL_NAMES[] = { + "OFF", + "AUTO", + "ON", + 0 +}; const char *ObSysVarFactory::SYS_VAR_NAMES_SORTED_BY_NAME[] = { "_aggregation_optimization_settings", @@ -619,6 +625,7 @@ const char *ObSysVarFactory::SYS_VAR_NAMES_SORTED_BY_NAME[] = { "disabled_storage_engines", "disconnect_on_expired_password", "div_precision_increment", + "enable_optimizer_rowgoal", "enable_sql_plan_monitor", "enforce_gtid_consistency", "eq_range_index_dive_limit", @@ -1235,6 +1242,7 @@ const ObSysVarClassType ObSysVarFactory::SYS_VAR_IDS_SORTED_BY_NAME[] = { SYS_VAR_DISABLED_STORAGE_ENGINES, SYS_VAR_DISCONNECT_ON_EXPIRED_PASSWORD, SYS_VAR_DIV_PRECISION_INCREMENT, + SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL, SYS_VAR_ENABLE_SQL_PLAN_MONITOR, SYS_VAR_ENFORCE_GTID_CONSISTENCY, SYS_VAR_EQ_RANGE_INDEX_DIVE_LIMIT, @@ -2360,7 +2368,8 @@ const char *ObSysVarFactory::SYS_VAR_NAMES_SORTED_BY_ID[] = { "_optimizer_cost_based_transformation", "range_index_dive_limit", "partition_index_dive_limit", - "ob_table_access_policy" + "ob_table_access_policy", + "enable_optimizer_rowgoal" }; bool ObSysVarFactory::sys_var_name_case_cmp(const char *name1, const ObString &name2) @@ -3178,6 +3187,7 @@ int ObSysVarFactory::create_all_sys_vars() + sizeof(ObSysVarRangeIndexDiveLimit) + sizeof(ObSysVarPartitionIndexDiveLimit) + sizeof(ObSysVarObTableAccessPolicy) + + sizeof(ObSysVarEnableOptimizerRowgoal) ; void *ptr = NULL; if (OB_ISNULL(ptr = allocator_.alloc(total_mem_size))) { @@ -8703,6 +8713,15 @@ int ObSysVarFactory::create_all_sys_vars() ptr = (void *)((char *)ptr + sizeof(ObSysVarObTableAccessPolicy)); } } + if (OB_SUCC(ret)) { + if (OB_ISNULL(sys_var_ptr = new (ptr)ObSysVarEnableOptimizerRowgoal())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to new ObSysVarEnableOptimizerRowgoal", K(ret)); + } else { + store_buf_[ObSysVarsToIdxMap::get_store_idx(static_cast(SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL))] = sys_var_ptr; + ptr = (void *)((char *)ptr + sizeof(ObSysVarEnableOptimizerRowgoal)); + } + } } return ret; @@ -15456,6 +15475,17 @@ int ObSysVarFactory::create_sys_var(ObIAllocator &allocator_, ObSysVarClassType } break; } + case SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL: { + void *ptr = NULL; + if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObSysVarEnableOptimizerRowgoal)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to alloc memory", K(ret), K(sizeof(ObSysVarEnableOptimizerRowgoal))); + } else if (OB_ISNULL(sys_var_ptr = new (ptr)ObSysVarEnableOptimizerRowgoal())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to new ObSysVarEnableOptimizerRowgoal", K(ret)); + } + break; + } default: { ret = OB_ERR_UNEXPECTED; diff --git a/src/share/system_variable/ob_system_variable_factory.h b/src/share/system_variable/ob_system_variable_factory.h index e82c72993..895937e9b 100644 --- a/src/share/system_variable/ob_system_variable_factory.h +++ b/src/share/system_variable/ob_system_variable_factory.h @@ -4472,6 +4472,15 @@ public: inline virtual ObSysVarClassType get_type() const { return SYS_VAR_OB_TABLE_ACCESS_POLICY; } inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(612); } }; +class ObSysVarEnableOptimizerRowgoal : public ObEnumSysVar +{ +public: + const static char * ENABLE_OPTIMIZER_ROWGOAL_NAMES[]; +public: + ObSysVarEnableOptimizerRowgoal() : ObEnumSysVar(ENABLE_OPTIMIZER_ROWGOAL_NAMES, NULL, NULL, NULL, NULL, NULL) {} + inline virtual ObSysVarClassType get_type() const { return SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL; } + inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(613); } +}; class ObSysVarFactory @@ -4495,7 +4504,7 @@ private: public: const static int64_t MYSQL_SYS_VARS_COUNT = 99; - const static int64_t OB_SYS_VARS_COUNT = 514; + const static int64_t OB_SYS_VARS_COUNT = 515; const static int64_t ALL_SYS_VARS_COUNT = MYSQL_SYS_VARS_COUNT + OB_SYS_VARS_COUNT; const static int64_t INVALID_MAX_READ_STALE_TIME = -1; diff --git a/src/share/system_variable/ob_system_variable_init.cpp b/src/share/system_variable/ob_system_variable_init.cpp index bedc63e52..d8f7e7f15 100644 --- a/src/share/system_variable/ob_system_variable_init.cpp +++ b/src/share/system_variable/ob_system_variable_init.cpp @@ -8538,13 +8538,27 @@ static struct VarsInit{ ObSysVars[612].alias_ = "OB_SV_TABLE_ACCESS_POLICY" ; }(); + [&] (){ + ObSysVars[613].default_value_ = "1" ; + ObSysVars[613].info_ = "Control whether the optimizer considers the impact of rowgoal (such as the LIMIT operator, etc.) during cardinality estimation." ; + ObSysVars[613].name_ = "enable_optimizer_rowgoal" ; + ObSysVars[613].data_type_ = ObIntType ; + ObSysVars[613].enum_names_ = "[u'OFF', u'AUTO', u'ON']" ; + ObSysVars[613].flags_ = ObSysVarFlag::GLOBAL_SCOPE | ObSysVarFlag::SESSION_SCOPE ; + ObSysVars[613].id_ = SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL ; + cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL)) ; + ObSysVarsIdToArrayIdx[SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL] = 613 ; + ObSysVars[613].base_value_ = "1" ; + ObSysVars[613].alias_ = "OB_SV_ENABLE_OPTIMIZER_ROWGOAL" ; + }(); + if (cur_max_var_id >= ObSysVarFactory::OB_MAX_SYS_VAR_ID) { HasInvalidSysVar = true; } } }vars_init; -static int64_t var_amount = 613; +static int64_t var_amount = 614; int64_t ObSysVariables::get_all_sys_var_count(){ return ObSysVarFactory::ALL_SYS_VARS_COUNT;} ObSysVarClassType ObSysVariables::get_sys_var_id(int64_t i){ return ObSysVars[i].id_;} diff --git a/src/share/system_variable/ob_system_variable_init.json b/src/share/system_variable/ob_system_variable_init.json index e927450bd..48f9647ee 100644 --- a/src/share/system_variable/ob_system_variable_init.json +++ b/src/share/system_variable/ob_system_variable_init.json @@ -11923,5 +11923,23 @@ "background_cn": "", "ref_url": "", "placeholder": true + }, + "enable_optimizer_rowgoal": { + "id": 10747, + "name": "enable_optimizer_rowgoal", + "default_value": "1", + "base_value": "1", + "data_type": "enum", + "info": "Control whether the optimizer considers the impact of rowgoal (such as the LIMIT operator, etc.) during cardinality estimation.", + "flags": "GLOBAL | SESSION ", + "enum_names": [ + "OFF", + "AUTO", + "ON" + ], + "publish_version": "435", + "info_cn": "控制优化器在基数估计时是否考虑行数目标(如 LIMIT 算子等)的影响", + "background_cn": "", + "ref_url": "" } } diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index 3945a78fa..a20e48882 100755 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -8287,7 +8287,8 @@ int JoinPath::get_re_estimate_param(EstimateCostInfo ¶m, left_param.override_ = param.override_; right_param.override_ = param.override_; right_param.need_batch_rescan_ = can_use_batch_nlj_; - if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_)) { + if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_) || + OB_ISNULL(parent_) || OB_ISNULL(parent_->get_plan())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(left_path_), K(right_path_), K(ret)); } else if (OB_UNLIKELY(param.need_parallel_ < ObGlobalHint::DEFAULT_PARALLEL)) { @@ -8317,7 +8318,8 @@ int JoinPath::get_re_estimate_param(EstimateCostInfo ¶m, } if (right_path_->is_inner_path() && (right_param.need_row_count_ > 1 || right_param.need_row_count_ < 0) - && (LEFT_SEMI_JOIN == join_type_ || LEFT_ANTI_JOIN == join_type_)) { + && (LEFT_SEMI_JOIN == join_type_ || LEFT_ANTI_JOIN == join_type_) + && ObEnableOptRowGoal::OFF != parent_->get_plan()->get_optimizer_context().get_enable_opt_row_goal()) { right_param.need_row_count_ = 1; } diff --git a/src/sql/optimizer/ob_log_table_scan.cpp b/src/sql/optimizer/ob_log_table_scan.cpp index 0393db7e7..5aaad356a 100644 --- a/src/sql/optimizer/ob_log_table_scan.cpp +++ b/src/sql/optimizer/ob_log_table_scan.cpp @@ -188,9 +188,13 @@ int ObLogTableScan::do_re_est_cost(EstimateCostInfo ¶m, double &card, double } est_cost_info_->limit_rows_ = limit_count; } - if (stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_2_3, COMPAT_VERSION_4_3_0, - COMPAT_VERSION_4_3_2) && + if (ObEnableOptRowGoal::OFF == get_plan()->get_optimizer_context().get_enable_opt_row_goal()) { + param.need_row_count_ = -1; + est_cost_info_->limit_rows_ = -1; + } else if (stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_2_3, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_2) && range_conds_.empty() && + ObEnableOptRowGoal::AUTO == get_plan()->get_optimizer_context().get_enable_opt_row_goal() && (!est_cost_info_->postfix_filters_.empty() || !est_cost_info_->table_filters_.empty() || !est_cost_info_->ss_postfix_range_filters_.empty())) { diff --git a/src/sql/optimizer/ob_logical_operator.cpp b/src/sql/optimizer/ob_logical_operator.cpp index 9ed06c95a..96f5527d5 100644 --- a/src/sql/optimizer/ob_logical_operator.cpp +++ b/src/sql/optimizer/ob_logical_operator.cpp @@ -1123,7 +1123,14 @@ int ObLogicalOperator::re_est_cost(EstimateCostInfo ¶m, double &card, double bool contain_false_filter = false; card = 0.0; cost = 0.0; - if (!param.need_re_est(get_parallel(), get_card())) { // no need to re est cost + if (OB_ISNULL(get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (ObEnableOptRowGoal::OFF == get_plan()->get_optimizer_context().get_enable_opt_row_goal()) { + param.need_row_count_ = -1; + } + if (OB_FAIL(ret)) { + } else if (!param.need_re_est(get_parallel(), get_card())) { // no need to re est cost card = get_card(); cost = get_cost(); } else if (OB_FAIL(check_need_parallel_valid(parallel))) { @@ -1136,9 +1143,6 @@ int ObLogicalOperator::re_est_cost(EstimateCostInfo ¶m, double &card, double // never reach } else if (!param.override_) { /* do nothing */ - } else if (OB_ISNULL(get_plan())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); } else { set_op_cost(op_cost); set_cost(cost); diff --git a/src/sql/optimizer/ob_optimizer.cpp b/src/sql/optimizer/ob_optimizer.cpp index aa983dbd7..2c48132b7 100644 --- a/src/sql/optimizer/ob_optimizer.cpp +++ b/src/sql/optimizer/ob_optimizer.cpp @@ -638,6 +638,8 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt) { int ret = OB_SUCCESS; ObSQLSessionInfo *session_info = NULL; + int64_t rowgoal_type = -1; + const ObOptParamHint &opt_params = ctx_.get_global_hint().opt_params_; if (OB_ISNULL(session_info = ctx_.get_session_info())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(session_info), K(ret)); @@ -661,7 +663,13 @@ int ObOptimizer::init_env_info(ObDMLStmt &stmt) LOG_WARN("failed to init correlation model", K(ret)); } else if (OB_FAIL(init_table_access_policy(stmt, *session_info))) { LOG_WARN("failed to init table access policy", K(ret)); - } + } else if (OB_FAIL(opt_params.get_enum_sys_var(ObOptParamHint::ENABLE_OPTIMIZER_ROWGOAL, + session_info, + share::SYS_VAR_ENABLE_OPTIMIZER_ROWGOAL, + rowgoal_type))) { + LOG_WARN("failed to get hint param", K(ret)); + } else if (FALSE_IT(ctx_.set_enable_opt_row_goal(rowgoal_type))) { + } else { /*do nothing*/ } return ret; } diff --git a/src/sql/optimizer/ob_optimizer_context.h b/src/sql/optimizer/ob_optimizer_context.h index 67d63fafb..284026fef 100644 --- a/src/sql/optimizer/ob_optimizer_context.h +++ b/src/sql/optimizer/ob_optimizer_context.h @@ -57,6 +57,13 @@ enum class ObTableAccessPolicy { MAX }; +enum class ObEnableOptRowGoal { + OFF, + AUTO, + ON, + MAX +}; + typedef common::ObArray ObPlanNotes; //table location local index id related info //tablet_loc_id and ref_table_id_ are used to uniquely determine @@ -263,7 +270,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, table_access_policy_(ObTableAccessPolicy::AUTO), enable_new_query_range_(false), partition_wise_plan_enabled_(true), - enable_px_ordered_coord_(false) + enable_px_ordered_coord_(false), + enable_opt_row_goal_(ObEnableOptRowGoal::MAX) { } inline common::ObOptStatManager *get_opt_stat_manager() { return opt_stat_manager_; } inline void set_opt_stat_manager(common::ObOptStatManager *sm) { opt_stat_manager_ = sm; } @@ -690,6 +698,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, inline ObTableAccessPolicy get_table_acces_policy() const { return table_access_policy_; } inline void set_enable_new_query_range(bool v) { enable_new_query_range_ = v; } 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_; } private: ObSQLSessionInfo *session_info_; ObExecContext *exec_ctx_; @@ -796,6 +806,7 @@ private: bool enable_new_query_range_; bool partition_wise_plan_enabled_; bool enable_px_ordered_coord_; + ObEnableOptRowGoal enable_opt_row_goal_; }; } } diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index c8d20a468..d33827e06 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -975,6 +975,16 @@ bool ObOptParamHint::is_param_val_valid(const OptParamType param_type, const ObO || 0 == val.get_varchar().case_compare("false")); break; } + case ENABLE_OPTIMIZER_ROWGOAL: { + if (val.is_int()) { + is_valid = 0 <= val.get_int() && val.get_int() < static_cast(ObEnableOptRowGoal::MAX); + } else if (val.is_varchar()) { + int64_t type = OB_INVALID_ID; + ObSysVarEnableOptimizerRowgoal sv; + is_valid = (OB_SUCCESS == sv.find_type(val.get_varchar(), type)); + } + break; + } default: LOG_TRACE("invalid opt param val", K(param_type), K(val)); break; @@ -1128,6 +1138,13 @@ int ObOptParamHint::get_enum_opt_param(const OptParamType param_type, int64_t &v } break; } + case ENABLE_OPTIMIZER_ROWGOAL: { + ObSysVarEnableOptimizerRowgoal sv; + if (OB_FAIL(sv.find_type(obj.get_varchar(), val))) { + LOG_WARN("param obj is invalid", K(ret), K(obj)); + } + break; + } default: ret = OB_ERR_UNEXPECTED; LOG_WARN("enum param is invalid", K(ret), K(obj)); diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 1a6035486..1006fd55b 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -192,7 +192,8 @@ struct ObOptParamHint DEF(USE_HASH_ROLLUP,) \ DEF(ENABLE_PX_ORDERED_COORD,) \ DEF(LOB_ROWSETS_MAX_ROWS,) \ - DEF(ENABLE_ENUM_SET_SUBSCHEMA,) \ + DEF(ENABLE_ENUM_SET_SUBSCHEMA,) \ + DEF(ENABLE_OPTIMIZER_ROWGOAL,) \ DECLARE_ENUM(OptParamType, opt_param, OPT_PARAM_TYPE_DEF, static);