diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index af3d31bd2c..e263320538 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -73,6 +73,7 @@ int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info, const ObQueryRangeArray &ss_ranges = range_info.get_ss_ranges(); est_cost_info.ranges_.reset(); est_cost_info.ss_ranges_.reset(); + est_cost_info.at_most_one_range_ = false; // maintain query range info for(int64_t i = 0; OB_SUCC(ret) && i < ranges.count(); ++i) { if (OB_ISNULL(ranges.at(i))) { @@ -90,6 +91,37 @@ int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info, LOG_WARN("failed to add range", K(ret)); } else { /*do nothing*/ } } + + if (OB_SUCC(ret) && ranges.count() > 1) { + // if there is more than one range and it is exists exec params in ranges_exprs, check at most one range. + // for (min; max) range extract from range_exprs contain exec params, do nothing now. + ObSEArray cur_const_exprs; + ObSEArray columns; + bool has_exec_param = false; + if (OB_ISNULL(range_info.get_query_range())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected NULL", K(ret), K(range_info.get_query_range())); + } else if (OB_FAIL(check_has_exec_param(*range_info.get_query_range(), has_exec_param))) { + LOG_WARN("failed to check has exec param", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(range_info.get_query_range()->get_range_exprs(), + columns))) { + LOG_WARN("failed to extract column exprs", K(ret)); + } else if (columns.empty() || !has_exec_param) { + /* do nothing */ + } else if (OB_FAIL(ObOptimizerUtil::compute_const_exprs(range_info.get_query_range()->get_range_exprs(), + cur_const_exprs))) { + // for inner path, const expr is computed without pushdown filter. + // need compute const expr by range_exprs. + LOG_WARN("failed to compute const exprs", K(ret)); + } else { + bool at_most_one_range = true; + for (int64_t i = 0; at_most_one_range && i < columns.count(); ++i) { + at_most_one_range = ObOptimizerUtil::find_equal_expr(cur_const_exprs, columns.at(i), + get_output_equal_sets()); + } + est_cost_info.at_most_one_range_ = at_most_one_range; + } + } return ret; } @@ -997,7 +1029,7 @@ int ObJoinOrder::get_query_range_info(const uint64_t table_id, return ret; } -int ObJoinOrder::check_has_exec_param(ObQueryRange &query_range, +int ObJoinOrder::check_has_exec_param(const ObQueryRange &query_range, bool &has_exec_param) { int ret = OB_SUCCESS; diff --git a/src/sql/optimizer/ob_join_order.h b/src/sql/optimizer/ob_join_order.h index 455d1705ff..e9faaff5dd 100644 --- a/src/sql/optimizer/ob_join_order.h +++ b/src/sql/optimizer/ob_join_order.h @@ -2183,7 +2183,7 @@ struct NullAwareAntiJoinInfo { QueryRangeInfo &range_info, PathHelper &helper); - int check_has_exec_param(ObQueryRange &query_range, + int check_has_exec_param(const ObQueryRange &query_range, bool &has_exec_param); int get_preliminary_prefix_info(ObQueryRange &query_range,QueryRangeInfo &range_info); diff --git a/src/sql/optimizer/ob_opt_est_cost_model.cpp b/src/sql/optimizer/ob_opt_est_cost_model.cpp index 2bdc8e9bd2..3f9d393170 100644 --- a/src/sql/optimizer/ob_opt_est_cost_model.cpp +++ b/src/sql/optimizer/ob_opt_est_cost_model.cpp @@ -102,6 +102,7 @@ int ObCostTableScanInfo::assign(const ObCostTableScanInfo &est_cost_info) batch_type_ = est_cost_info.batch_type_; sample_info_ = est_cost_info.sample_info_; use_column_store_ = est_cost_info.use_column_store_; + at_most_one_range_ = est_cost_info.at_most_one_range_; // no need to copy table scan param } return ret; @@ -1773,7 +1774,11 @@ int ObOptEstCostModel::range_scan_cpu_cost(const ObCostTableScanInfo &est_cost_i } // CPU代价,包括get_next_row调用的代价和谓词代价 double range_cost = 0; - range_cost = est_cost_info.ranges_.count() * cost_params_.get_range_cost(sys_stat_); + double range_count = est_cost_info.ranges_.count(); + if (range_count > 1 && est_cost_info.at_most_one_range_) { + range_count = 1; + } + range_cost = range_count * cost_params_.get_range_cost(sys_stat_); cost = row_count * cost_params_.get_cpu_tuple_cost(sys_stat_); cost += range_cost + qual_cost + project_cost; diff --git a/src/sql/optimizer/ob_opt_est_cost_model.h b/src/sql/optimizer/ob_opt_est_cost_model.h index ff63271329..61a7e507ca 100644 --- a/src/sql/optimizer/ob_opt_est_cost_model.h +++ b/src/sql/optimizer/ob_opt_est_cost_model.h @@ -229,7 +229,8 @@ struct ObCostTableScanInfo index_back_row_count_(0.0), output_row_count_(0.0), batch_type_(common::ObSimpleBatch::ObBatchType::T_NONE), - use_column_store_(false) + use_column_store_(false), + at_most_one_range_(false) { } virtual ~ObCostTableScanInfo() { } @@ -290,7 +291,7 @@ struct ObCostTableScanInfo SampleInfo sample_info_; bool use_column_store_; common::ObSEArray column_group_infos_; - + bool at_most_one_range_; private: DISALLOW_COPY_AND_ASSIGN(ObCostTableScanInfo); };