diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index c44e8120cc..2b05ea3128 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -2430,6 +2430,23 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id, use_skip_scan = OptSkipScanState::SS_UNSET; } + if (OB_SUCC(ret) && OptSkipScanState::SS_DISABLE != use_skip_scan) { + // OptColumnMeta for prefix columns may be not added. It's needed to calculate prefix NDV + const ObIArray &column_items = index_info_entry->get_range_info().get_range_columns(); + const int64_t ss_offset = query_range->get_skip_scan_offset(); + const OptSelectivityCtx &ctx = get_plan()->get_selectivity_ctx(); + OptTableMeta *table_meta = NULL; + if (OB_UNLIKELY(column_items.count() < ss_offset) || + OB_ISNULL(table_meta = get_plan()->get_basic_table_metas().get_table_meta_by_table_id(table_id))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected params", K(ret), K(column_items.count()), K(ss_offset), K(table_meta)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < ss_offset; ++i) { + if (OB_FAIL(table_meta->add_column_meta_no_dup(column_items.at(i).column_id_ , ctx))) { + LOG_WARN("failed to add column meta no duplicate", K(ret)); + } + } + } LOG_TRACE("check use skip scan", K(helper.is_inner_path_), K(hint_force_skip_scan), K(hint_force_no_skip_scan), K(use_skip_scan)); return ret; diff --git a/src/sql/optimizer/ob_opt_selectivity.cpp b/src/sql/optimizer/ob_opt_selectivity.cpp index 0592f99cfe..0eb02d01e1 100644 --- a/src/sql/optimizer/ob_opt_selectivity.cpp +++ b/src/sql/optimizer/ob_opt_selectivity.cpp @@ -139,47 +139,74 @@ int OptTableMeta::init(const uint64_t table_id, } //init column ndv for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) { - column_id = column_ids.at(i); - int64_t global_ndv = 0; - int64_t num_null = 0; - bool is_single_pkey = (1 == pk_ids_.count() && pk_ids_.at(0) == column_id); - ObGlobalColumnStat stat; - if (is_single_pkey) { - global_ndv = rows_; - num_null = 0; - } else if (use_default_stat()) { - global_ndv = std::min(rows, 100L); - num_null = rows * EST_DEF_COL_NULL_RATIO; - } else if (OB_ISNULL(ctx.get_opt_stat_manager()) || OB_ISNULL(ctx.get_session_info())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(ctx.get_opt_stat_manager()), - K(ctx.get_session_info())); - } else if (OB_FAIL(ctx.get_opt_stat_manager()->get_column_stat(ctx.get_session_info()->get_effective_tenant_id(), - ref_table_id_, - all_used_part_id, - column_id, - all_used_global_parts, - rows, - scale_ratio, - stat))) { - LOG_WARN("failed to get column stats", K(ret)); - } else if (0 == stat.ndv_val_ && 0 == stat.null_val_) { - global_ndv = std::min(rows, 100L); - num_null = rows * EST_DEF_COL_NULL_RATIO; - } else if (0 == stat.ndv_val_ && stat.null_val_ > 0) { - global_ndv = 1; - num_null = stat.null_val_; - } else { - global_ndv = stat.ndv_val_; - num_null = stat.null_val_; - } - if (OB_SUCC(ret)) { - column_metas_.at(i).init(column_id, global_ndv, num_null, stat.avglen_val_); + if (OB_FAIL(init_column_meta(ctx, column_ids.at(i), column_metas_.at(i)))) { + LOG_WARN("failed to init column ", K(ret)); } } return ret; } +int OptTableMeta::init_column_meta(const OptSelectivityCtx &ctx, + const uint64_t column_id, + OptColumnMeta &col_meta) +{ + int ret = OB_SUCCESS; + ObGlobalColumnStat stat; + bool is_single_pkey = (1 == pk_ids_.count() && pk_ids_.at(0) == column_id); + int64_t global_ndv = 0; + int64_t num_null = 0; + if (is_single_pkey) { + global_ndv = rows_; + num_null = 0; + } else if (use_default_stat()) { + global_ndv = std::min(rows_, 100.0); + num_null = rows_ * EST_DEF_COL_NULL_RATIO; + } else if (OB_ISNULL(ctx.get_opt_stat_manager()) || OB_ISNULL(ctx.get_session_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(ctx.get_opt_stat_manager()), + K(ctx.get_session_info())); + } else if (OB_FAIL(ctx.get_opt_stat_manager()->get_column_stat(ctx.get_session_info()->get_effective_tenant_id(), + ref_table_id_, + all_used_parts_, + column_id, + all_used_global_parts_, + rows_, + scale_ratio_, + stat))) { + LOG_WARN("failed to get column stats", K(ret)); + } else if (0 == stat.ndv_val_ && 0 == stat.null_val_) { + global_ndv = std::min(rows_, 100.0); + num_null = rows_ * EST_DEF_COL_NULL_RATIO; + } else if (0 == stat.ndv_val_ && stat.null_val_ > 0) { + global_ndv = 1; + num_null = stat.null_val_; + } else { + global_ndv = stat.ndv_val_; + num_null = stat.null_val_; + } + + if (OB_SUCC(ret)) { + col_meta.init(column_id, global_ndv, num_null, stat.avglen_val_); + } + return ret; +} + +int OptTableMeta::add_column_meta_no_dup(const uint64_t column_id, + const OptSelectivityCtx &ctx) +{ + int ret = OB_SUCCESS; + OptColumnMeta *col_meta = NULL; + if (NULL != OptTableMeta::get_column_meta(column_id)) { + /* do nothing */ + } else if (OB_ISNULL(col_meta = column_metas_.alloc_place_holder())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate place holder for column meta", K(ret)); + } else if (OB_FAIL(init_column_meta(ctx, column_id, *col_meta))) { + LOG_WARN("failed to init column meta", K(ret)); + } + return ret; +} + const OptColumnMeta* OptTableMeta::get_column_meta(const uint64_t column_id) const { const OptColumnMeta* column_meta = NULL; diff --git a/src/sql/optimizer/ob_opt_selectivity.h b/src/sql/optimizer/ob_opt_selectivity.h index b451c9a317..f40322d7f3 100644 --- a/src/sql/optimizer/ob_opt_selectivity.h +++ b/src/sql/optimizer/ob_opt_selectivity.h @@ -246,6 +246,12 @@ public: // int update_stat(const double rows, const bool can_reduce, const bool can_enlarge); + int init_column_meta(const OptSelectivityCtx &ctx, + const uint64_t column_id, + OptColumnMeta &col_meta); + + int add_column_meta_no_dup(const uint64_t column_id, const OptSelectivityCtx &ctx); + const OptColumnMeta* get_column_meta(const uint64_t column_id) const; uint64_t get_table_id() const { return table_id_; }