diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index b7f7574a5b..6779d60f13 100755 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1593,6 +1593,9 @@ DEF_TIME(_stall_threshold_for_dynamic_worker, OB_TENANT_PARAMETER, "3ms", "[0ms, DEF_BOOL(_optimizer_better_inlist_costing, OB_TENANT_PARAMETER, "False", "enable improved costing of index access using in-list(s)", ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_BOOL(_optimizer_skip_scan_enabled, OB_TENANT_PARAMETER, "False", + "enable/disable index skip scan", + ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); DEF_TIME(_ls_migration_wait_completing_timeout, OB_TENANT_PARAMETER, "30m", "[60s,)", "the wait timeout in ls complete migration phase", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index c45040ab7a..a47c2e771d 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -2293,6 +2293,7 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id, ObOptimizerContext *opt_ctx = NULL; const ParamStore *params = NULL; bool is_valid = true; + ObSQLSessionInfo *session_info = NULL; ObSEArray skyline_index_ids; if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt()) || @@ -2300,7 +2301,8 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id, OB_ISNULL(params = opt_ctx->get_params()) || OB_ISNULL(opt_ctx->get_exec_ctx()) || OB_ISNULL(opt_ctx->get_exec_ctx()->get_sql_ctx()) || - OB_ISNULL(helper.table_opt_info_)) { + OB_ISNULL(helper.table_opt_info_) || + OB_ISNULL(session_info = opt_ctx->get_session_info())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("get unexpected null", K(get_plan()), K(opt_ctx), K(params), K(stmt), K(ret)); @@ -2354,6 +2356,7 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id, skyline_index_ids.at(i), index_info_cache, helper, + session_info, use_skip_scan))) { LOG_WARN("failed to check will use skip scan", K(ret)); } else if (is_create_das_path && @@ -2391,6 +2394,7 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id, const uint64_t index_id, const ObIndexInfoCache &index_info_cache, PathHelper &helper, + ObSQLSessionInfo *session_info, OptSkipScanState &use_skip_scan) { int ret = OB_SUCCESS; @@ -2403,6 +2407,8 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id, OB_ISNULL(get_plan())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ref_id), K(index_id), K(get_plan()), K(ret)); + } else if (!session_info->is_index_skip_scan_enabled()) { + use_skip_scan = OptSkipScanState::SS_DISABLE; } else if (is_virtual_table(ref_id)) { use_skip_scan = OptSkipScanState::SS_DISABLE; } else if (OB_FAIL(index_info_cache.get_index_info_entry(table_id, index_id, diff --git a/src/sql/optimizer/ob_join_order.h b/src/sql/optimizer/ob_join_order.h index 5f76b6739d..bc2007c592 100644 --- a/src/sql/optimizer/ob_join_order.h +++ b/src/sql/optimizer/ob_join_order.h @@ -1561,6 +1561,7 @@ struct NullAwareAntiJoinInfo { const uint64_t index_id, const ObIndexInfoCache &index_info_cache, PathHelper &helper, + ObSQLSessionInfo *session_info, OptSkipScanState &use_skip_scan); int get_access_path_ordering(const uint64_t table_id, diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index 348c75b30d..e3baae81c7 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -499,6 +499,17 @@ int ObSQLSessionInfo::is_better_inlist_enabled(bool &enabled) const return ret; } +bool ObSQLSessionInfo::is_index_skip_scan_enabled() const +{ + bool bret = false; + int64_t tenant_id = get_effective_tenant_id(); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id)); + if (tenant_config.is_valid()) { + bret = tenant_config->_optimizer_skip_scan_enabled; + } + return bret; +} + void ObSQLSessionInfo::destroy(bool skip_sys_var) { if (is_inited_) { diff --git a/src/sql/session/ob_sql_session_info.h b/src/sql/session/ob_sql_session_info.h index ce712266aa..dd83fc771d 100644 --- a/src/sql/session/ob_sql_session_info.h +++ b/src/sql/session/ob_sql_session_info.h @@ -1147,6 +1147,7 @@ public: int is_groupby_placement_transformation_enabled(bool &transformation_enabled) const; bool is_in_range_optimization_enabled() const; int is_better_inlist_enabled(bool &enabled) const; + bool is_index_skip_scan_enabled() const; ObSessionDDLInfo &get_ddl_info() { return ddl_info_; } void set_ddl_info(const ObSessionDDLInfo &ddl_info) { ddl_info_ = ddl_info; } diff --git a/src/storage/access/ob_multiple_skip_scan_merge.cpp b/src/storage/access/ob_multiple_skip_scan_merge.cpp index 094b3eb4b3..d08931ffb8 100644 --- a/src/storage/access/ob_multiple_skip_scan_merge.cpp +++ b/src/storage/access/ob_multiple_skip_scan_merge.cpp @@ -27,6 +27,7 @@ ObMultipleSkipScanMerge::ObMultipleSkipScanMerge() datums_cnt_(0), datums_(nullptr), origin_range_(nullptr), + skip_scan_range_(nullptr), range_allocator_("SS_RANGE"), rowkey_allocator_("SS_ROWKEY") { @@ -61,8 +62,6 @@ int ObMultipleSkipScanMerge::init( } else if (FALSE_IT(datums_ = new (buf) ObStorageDatum[datums_cnt_])) { } else if (OB_FAIL(prepare_range(start_key_of_scan_rowkey_range(), scan_rowkey_range_))) { STORAGE_LOG(WARN, "Fail to prepare distinct scan range", K(ret)); - } else if (OB_FAIL(prepare_range(start_key_of_scan_rows_range(), scan_rows_range_))) { - STORAGE_LOG(WARN, "Fail to prepare skip scan range", K(ret)); } else { STORAGE_LOG(DEBUG, "success to init ObMultipleSkipScanMerge", K(param), K(context), K(get_table_param), K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_)); @@ -85,6 +84,7 @@ void ObMultipleSkipScanMerge::reset() } datums_ = nullptr; origin_range_ = nullptr; + skip_scan_range_ = nullptr; range_allocator_.reset(); rowkey_allocator_.reset(); ObMultipleScanMerge::reset(); @@ -107,6 +107,7 @@ int ObMultipleSkipScanMerge::open(const blocksstable::ObDatumRange &range, const { int ret = OB_SUCCESS; origin_range_ = ⦥ + skip_scan_range_ = &skip_scan_range; if (RETIRED_TO_SCAN == state_) { if (OB_FAIL(ObMultipleScanMerge::open(range))) { STORAGE_LOG(WARN, "Fail to open ObMultipleScanMerge", K(ret), K(range)); @@ -138,20 +139,6 @@ int ObMultipleSkipScanMerge::open_skip_scan(const blocksstable::ObDatumRange &ra prepare_rowkey(end_key_of_scan_rowkey_range(), range.end_key_, schema_rowkey_cnt_, false); scan_rowkey_range_.set_border_flag(range.get_border_flag()); scan_rowkey_range_.set_group_idx(range.get_group_idx()); - // generate key range for outputing rows - for (int64_t i = 0; i < ss_rowkey_prefix_cnt_; ++i) { - start_key_of_scan_rows_range()[i].set_min(); - end_key_of_scan_rows_range()[i].set_max(); - } - prepare_rowkey(start_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_, - skip_scan_range.start_key_, - schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_, - true); - prepare_rowkey(end_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_, - skip_scan_range.end_key_, - schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_, - false); - scan_rows_range_.set_border_flag(skip_scan_range.get_border_flag()); scan_rowkey_range_.set_group_idx(range.get_group_idx()); const ObColDescIArray *col_descs = nullptr; if (OB_ISNULL(col_descs = access_param_->iter_param_.get_out_col_descs())) { @@ -159,8 +146,6 @@ int ObMultipleSkipScanMerge::open_skip_scan(const blocksstable::ObDatumRange &ra TRANS_LOG(WARN, "Unexpected null out cols", K(ret)); } else if (OB_FAIL(scan_rowkey_range_.prepare_memtable_readable(*col_descs, rowkey_allocator_))) { STORAGE_LOG(WARN, "Fail to transfer store rowkey", K(ret), K(scan_rowkey_range_)); - } else if (OB_FAIL(scan_rows_range_.prepare_memtable_readable(*col_descs, range_allocator_))) { - STORAGE_LOG(WARN, "Fail to transfer store rowkey", K(ret), K(scan_rows_range_)); } STORAGE_LOG(TRACE, "open skip scan", K(ret), K(schema_rowkey_cnt_), K(ss_rowkey_prefix_cnt_), K(scan_rows_range_), K(range), K(skip_scan_range)); @@ -390,6 +375,8 @@ int ObMultipleSkipScanMerge::update_scan_rows_range(blocksstable::ObDatumRow &ro range_allocator_.reuse(); if (should_check_interrupt() && OB_FAIL(THIS_WORKER.check_status())) { STORAGE_LOG(WARN, "query interrupt", K(ret)); + } else if (OB_FAIL(prepare_scan_row_range())) { + STORAGE_LOG(WARN, "Fail to prepare scan row range", K(ret)); } else if (should_retire_to_scan()) { // too many distinct prefix, retire to normal scan for (int64_t i = 0; OB_SUCC(ret) && i < ss_rowkey_prefix_cnt_; ++i) { @@ -404,8 +391,10 @@ int ObMultipleSkipScanMerge::update_scan_rows_range(blocksstable::ObDatumRow &ro if (OB_FAIL(ret)) { } else if (access_ctx_->query_flag_.is_reverse_scan()) { scan_rows_range_.set_start_key(origin_range_->get_start_key()); + set_border_falg(true, *origin_range_, scan_rows_range_); } else { scan_rows_range_.set_end_key(origin_range_->get_end_key()); + set_border_falg(false, *origin_range_, scan_rows_range_); } STORAGE_LOG(TRACE, "should retire to normal scan", K(ret), K(scan_rows_range_)); } else { @@ -422,10 +411,10 @@ int ObMultipleSkipScanMerge::update_scan_rows_range(blocksstable::ObDatumRow &ro } } if (OB_SUCC(ret)) { - // check current skip scan range may exceed original range? + // adjust scan rows range according original query range // one case is in parallel execution, splitted range bool exceeded = false; - if (OB_FAIL(check_range_exceeded(exceeded))) { + if (OB_FAIL(shrink_scan_rows_range(exceeded))) { STORAGE_LOG(WARN, "Fail to check range exceed", K(ret)); } else if (exceeded) { ret = OB_ITER_END; @@ -494,23 +483,79 @@ int ObMultipleSkipScanMerge::update_scan_rowkey_range() return ret; } -int ObMultipleSkipScanMerge::check_range_exceeded(bool &exceeded) +int ObMultipleSkipScanMerge::shrink_scan_rows_range(bool &exceeded) { int ret = OB_SUCCESS; int cmp_ret = 0; - exceeded = false; const ObStorageDatumUtils &datum_utils = access_param_->iter_param_.get_read_info()->get_datum_utils(); - if (OB_FAIL(scan_rows_range_.end_key_.compare(scan_rowkey_range_.start_key_, datum_utils, cmp_ret))) { - STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rows_range_.end_key_), K(scan_rowkey_range_.start_key_)); - } else if (cmp_ret < 0 || (0 == cmp_ret && (scan_rows_range_.is_right_open() || scan_rowkey_range_.is_left_open()))) { - exceeded = true; - } else if (OB_FAIL(scan_rows_range_.start_key_.compare(scan_rowkey_range_.end_key_, datum_utils, cmp_ret))) { - STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rows_range_.end_key_), K(scan_rowkey_range_.start_key_)); - } else if (cmp_ret > 0 || (0 == cmp_ret && (scan_rows_range_.is_left_open() || scan_rowkey_range_.is_right_open()))) { + if (OB_FAIL(scan_rows_range_.start_key_.compare(origin_range_->start_key_, datum_utils, cmp_ret))) { + STORAGE_LOG(WARN, "Fail to compare", K(ret)); + } else if (cmp_ret > 0) { + } else { + set_border_falg(true, *origin_range_, scan_rows_range_); + if (cmp_ret < 0) { + scan_rows_range_.start_key_ = origin_range_->start_key_; + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(scan_rows_range_.end_key_.compare(origin_range_->end_key_, datum_utils, cmp_ret))) { + STORAGE_LOG(WARN, "Fail to compare", K(ret)); + } else if (cmp_ret < 0) { + } else { + set_border_falg(false, *origin_range_, scan_rows_range_); + if (cmp_ret > 0) { + scan_rows_range_.end_key_ = origin_range_->end_key_; + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(scan_rows_range_.start_key_.compare(scan_rows_range_.end_key_, datum_utils, cmp_ret))) { + STORAGE_LOG(WARN, "Fail to compare", K(ret), K(scan_rows_range_)); + } else if (cmp_ret > 0 || (0 == cmp_ret && (scan_rows_range_.is_left_open() || scan_rows_range_.is_right_open()))) { exceeded = true; } return ret; } +int ObMultipleSkipScanMerge::prepare_scan_row_range() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(prepare_range(start_key_of_scan_rows_range(), scan_rows_range_))) { + STORAGE_LOG(WARN, "Fail to prepare skip scan range", K(ret)); + } else { + for (int64_t i = 0; i < ss_rowkey_prefix_cnt_; ++i) { + start_key_of_scan_rows_range()[i].set_min(); + end_key_of_scan_rows_range()[i].set_max(); + } + prepare_rowkey(start_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_, + skip_scan_range_->start_key_, + schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_, + true); + prepare_rowkey(end_key_of_scan_rows_range() + ss_rowkey_prefix_cnt_, + skip_scan_range_->end_key_, + schema_rowkey_cnt_ - ss_rowkey_prefix_cnt_, + false); + scan_rows_range_.set_border_flag(skip_scan_range_->get_border_flag()); + scan_rows_range_.set_group_idx(origin_range_->get_group_idx()); + } + return ret; +} + +void ObMultipleSkipScanMerge::set_border_falg(const bool is_left, const blocksstable::ObDatumRange &src, blocksstable::ObDatumRange &dst) +{ + if (is_left) { + if (src.is_left_open()) { + dst.set_left_open(); + } else { + dst.set_left_closed(); + } + } else { + if (src.is_right_open()) { + dst.set_right_open(); + } else { + dst.set_right_closed(); + } + } +} + } } diff --git a/src/storage/access/ob_multiple_skip_scan_merge.h b/src/storage/access/ob_multiple_skip_scan_merge.h index 040a291cfc..fc89710afc 100644 --- a/src/storage/access/ob_multiple_skip_scan_merge.h +++ b/src/storage/access/ob_multiple_skip_scan_merge.h @@ -51,7 +51,9 @@ private: const int64_t datum_cnt, const bool is_min); int update_scan_rowkey_range(); int update_scan_rows_range(blocksstable::ObDatumRow &row); - int check_range_exceeded(bool &exceeded); + int shrink_scan_rows_range(bool &exceeded); + int prepare_scan_row_range(); + void set_border_falg(const bool is_left, const blocksstable::ObDatumRange &src, blocksstable::ObDatumRange &dst); OB_INLINE blocksstable::ObStorageDatum* start_key_of_scan_rowkey_range() { return datums_ + START_KEY_OFFSET_OF_SCAN_ROWKEY_RANGE * schema_rowkey_cnt_; } OB_INLINE blocksstable::ObStorageDatum* end_key_of_scan_rowkey_range() @@ -94,6 +96,7 @@ private: int64_t datums_cnt_; blocksstable::ObStorageDatum *datums_; const blocksstable::ObDatumRange *origin_range_; + const blocksstable::ObDatumRange *skip_scan_range_; common::ObArenaAllocator range_allocator_; common::ObArenaAllocator rowkey_allocator_; }; 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 c265011ec6..e4f67021fb 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,6 +336,7 @@ _ob_trans_rpc_timeout _optimizer_ads_time_limit _optimizer_better_inlist_costing _optimizer_group_by_placement +_optimizer_skip_scan_enabled _optimizer_sortmerge_join_enabled _parallel_max_active_sessions _parallel_min_message_pool