925 lines
33 KiB
C++
925 lines
33 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#ifndef OCEANBASE_SQL_OPTIMIZER_OB_OPT_EST_COST_MODEL_
|
|
#define OCEANBASE_SQL_OPTIMIZER_OB_OPT_EST_COST_MODEL_
|
|
#include "lib/container/ob_array.h"
|
|
#include "common/object/ob_object.h"
|
|
#include "share/ob_simple_batch.h"
|
|
#include "share/ob_rpc_struct.h"
|
|
#include "sql/rewrite/ob_query_range_provider.h"
|
|
#include "sql/optimizer/ob_opt_default_stat.h"
|
|
#include "sql/resolver/dml/ob_dml_stmt.h"
|
|
#include "share/stat/ob_opt_ds_stat.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace sql
|
|
{
|
|
struct OrderItem;
|
|
struct ObExprSelPair;
|
|
struct JoinFilterInfo;
|
|
class OptTableMetas;
|
|
class OptSelectivityCtx;
|
|
class ObOptCostModelParameter;
|
|
class OptSystemStat;
|
|
|
|
enum RowCountEstMethod { INVALID_METHOD = 0 }; // deprecated
|
|
enum ObBaseTableEstBasicMethod
|
|
{
|
|
EST_INVALID = 0,
|
|
EST_DEFAULT = 1 << 0,
|
|
EST_STAT = 1 << 1,
|
|
EST_STORAGE = 1 << 2,
|
|
EST_DS_BASIC = 1 << 3,
|
|
EST_DS_FULL = 1 << 4,
|
|
};
|
|
typedef uint64_t ObBaseTableEstMethod;
|
|
|
|
// all the table meta info need to compute cost
|
|
struct ObTableMetaInfo
|
|
{
|
|
ObTableMetaInfo(uint64_t ref_table_id)
|
|
: ref_table_id_(ref_table_id),
|
|
schema_version_(share::OB_INVALID_SCHEMA_VERSION),
|
|
part_count_(0),
|
|
micro_block_size_(0),
|
|
table_column_count_(0),
|
|
table_rowkey_count_(0),
|
|
table_row_count_(0),
|
|
part_size_(0),
|
|
average_row_size_(0),
|
|
row_count_(0),
|
|
has_opt_stat_(false),
|
|
micro_block_count_(-1),
|
|
table_type_(share::schema::MAX_TABLE_TYPE)
|
|
{ }
|
|
virtual ~ObTableMetaInfo()
|
|
{ }
|
|
|
|
void assign(const ObTableMetaInfo &table_meta_info);
|
|
double get_micro_block_numbers() const;
|
|
TO_STRING_KV(K_(ref_table_id), K_(part_count), K_(micro_block_size),
|
|
K_(part_size), K_(average_row_size), K_(table_column_count),
|
|
K_(table_rowkey_count), K_(table_row_count), K_(row_count),
|
|
K_(micro_block_count), K_(table_type));
|
|
|
|
/// the following fields come from schema info
|
|
uint64_t ref_table_id_; //ref table id
|
|
int64_t schema_version_; // schema version
|
|
int64_t part_count_; //partition count
|
|
int64_t micro_block_size_; //main table micro block size
|
|
int64_t table_column_count_; // table column count
|
|
int64_t table_rowkey_count_; // table rowkey count, used in index_back cost calc.index_back时候会从索引表获取主键
|
|
|
|
/// the following fields come from access path estimation
|
|
int64_t table_row_count_; // table row count in stat.
|
|
double part_size_; //main table best partition data size
|
|
double average_row_size_; //main table best partition average row size
|
|
|
|
double row_count_; // row count after filters, estimated by stat manager
|
|
bool has_opt_stat_;
|
|
int64_t micro_block_count_; // main table micro block count
|
|
share::schema::ObTableType table_type_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObTableMetaInfo);
|
|
};
|
|
|
|
// all the index meta info need to compute cost
|
|
struct ObIndexMetaInfo
|
|
{
|
|
ObIndexMetaInfo(uint64_t ref_table_id, uint64_t index_id)
|
|
: ref_table_id_(ref_table_id),
|
|
index_id_(index_id),
|
|
index_micro_block_size_(0),
|
|
index_part_count_(1),
|
|
index_part_size_(0),
|
|
index_column_count_(0),
|
|
is_index_back_(false),
|
|
is_unique_index_(false),
|
|
is_global_index_(false),
|
|
is_geo_index_(false),
|
|
index_micro_block_count_(-1)
|
|
{ }
|
|
virtual ~ObIndexMetaInfo()
|
|
{ }
|
|
void assign(const ObIndexMetaInfo &index_meta_info);
|
|
double get_micro_block_numbers() const;
|
|
TO_STRING_KV(K_(ref_table_id), K_(index_id), K_(index_micro_block_size),
|
|
K_(index_part_count), K_(index_part_size),
|
|
K_(index_column_count), K_(is_index_back),
|
|
K_(is_unique_index), K_(index_micro_block_count));
|
|
uint64_t ref_table_id_; // ref table id
|
|
uint64_t index_id_; // index id
|
|
int64_t index_micro_block_size_; //index micro block size, same as main table when path is primary
|
|
uint64_t index_part_count_;
|
|
double index_part_size_; //index table partition(0) data size, same as main table when path is primary
|
|
int64_t index_column_count_; //index column count
|
|
bool is_index_back_; // is index back
|
|
bool is_unique_index_; // is unique index
|
|
bool is_global_index_; // whether is global index
|
|
bool is_geo_index_; // whether is spatial index
|
|
int64_t index_micro_block_count_; // micro block count from table static info
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObIndexMetaInfo);
|
|
};
|
|
|
|
struct ObBasicCostInfo
|
|
{
|
|
ObBasicCostInfo() : rows_(0), cost_(0), width_(0), exchange_allocated_(false) {}
|
|
ObBasicCostInfo(double rows, double cost, double width, bool exchange_allocated = false)
|
|
: rows_(rows), cost_(cost), width_(width), exchange_allocated_(exchange_allocated)
|
|
{}
|
|
TO_STRING_KV(K_(rows), K_(cost), K_(width), K_(exchange_allocated));
|
|
double rows_;
|
|
double cost_;
|
|
double width_;
|
|
bool exchange_allocated_;
|
|
};
|
|
|
|
struct ObTwoNodeCostInfo
|
|
{
|
|
ObTwoNodeCostInfo(double left_rows, double left_width,
|
|
double right_rows, double right_width,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: left_rows_(left_rows),
|
|
left_width_(left_width),
|
|
right_rows_(right_rows),
|
|
right_width_(right_width),
|
|
table_metas_(table_metas),
|
|
sel_ctx_(sel_ctx)
|
|
{ }
|
|
const double left_rows_;
|
|
const double left_width_;
|
|
const double right_rows_;
|
|
const double right_width_;
|
|
OptTableMetas *table_metas_;
|
|
OptSelectivityCtx *sel_ctx_;
|
|
};
|
|
|
|
struct ObCostColumnGroupInfo {
|
|
ObCostColumnGroupInfo()
|
|
:micro_block_count_(0.0),
|
|
filter_sel_(1.0),
|
|
skip_rate_(1.0),
|
|
skip_filter_sel_(1.0)
|
|
{
|
|
}
|
|
int assign(const ObCostColumnGroupInfo& info);
|
|
|
|
TO_STRING_KV(
|
|
K_(filters),
|
|
K_(access_column_items),
|
|
K_(column_id),
|
|
K_(micro_block_count),
|
|
K_(filter_sel),
|
|
K_(skip_rate),
|
|
K_(skip_filter_sel)
|
|
);
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> filters_;
|
|
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> access_column_items_;
|
|
uint64_t column_id_;
|
|
int64_t micro_block_count_;
|
|
double filter_sel_;
|
|
double skip_rate_;
|
|
double skip_filter_sel_;
|
|
};
|
|
|
|
/*
|
|
* store all the info needed to cost table scan
|
|
*/
|
|
struct ObCostTableScanInfo
|
|
{
|
|
ObCostTableScanInfo(uint64_t table_id, uint64_t ref_table_id, uint64_t index_id)
|
|
: table_id_(table_id),
|
|
ref_table_id_(ref_table_id),
|
|
index_id_(index_id),
|
|
table_meta_info_(NULL),
|
|
index_meta_info_(ref_table_id, index_id),
|
|
is_virtual_table_(is_virtual_table(ref_table_id)),
|
|
is_unique_(false),
|
|
is_inner_path_(false),
|
|
can_use_batch_nlj_(false),
|
|
ranges_(),
|
|
ss_ranges_(),
|
|
range_columns_(),
|
|
prefix_filters_(),
|
|
pushdown_prefix_filters_(),
|
|
ss_postfix_range_filters_(),
|
|
postfix_filters_(),
|
|
table_filters_(),
|
|
table_metas_(NULL),
|
|
sel_ctx_(NULL),
|
|
est_method_(EST_INVALID),
|
|
prefix_filter_sel_(1.0),
|
|
pushdown_prefix_filter_sel_(1.0),
|
|
postfix_filter_sel_(1.0),
|
|
table_filter_sel_(1.0),
|
|
join_filter_sel_(1.0),
|
|
ss_prefix_ndv_(1.0),
|
|
ss_postfix_range_filters_sel_(1.0),
|
|
logical_query_range_row_count_(0.0),
|
|
phy_query_range_row_count_(0.0),
|
|
index_back_row_count_(0.0),
|
|
output_row_count_(0.0),
|
|
batch_type_(common::ObSimpleBatch::ObBatchType::T_NONE),
|
|
use_column_store_(false),
|
|
at_most_one_range_(false),
|
|
index_back_with_column_store_(false)
|
|
{ }
|
|
virtual ~ObCostTableScanInfo()
|
|
{ }
|
|
|
|
int assign(const ObCostTableScanInfo &other_est_cost_info);
|
|
|
|
TO_STRING_KV(K_(table_id), K_(ref_table_id), K_(index_id),
|
|
K_(table_meta_info), K_(index_meta_info),
|
|
K_(access_column_items),
|
|
K_(is_virtual_table), K_(is_unique),
|
|
K_(is_inner_path), K_(can_use_batch_nlj), K_(est_method),
|
|
K_(prefix_filter_sel), K_(pushdown_prefix_filter_sel),
|
|
K_(postfix_filter_sel), K_(table_filter_sel),
|
|
K_(ss_prefix_ndv), K_(ss_postfix_range_filters_sel),
|
|
K_(use_column_store),
|
|
K_(index_back_with_column_store),
|
|
K_(index_scan_column_group_infos),
|
|
K_(index_back_column_group_infos));
|
|
// the following information need to be set before estimating cost
|
|
uint64_t table_id_; // table id
|
|
uint64_t ref_table_id_; // ref table id
|
|
uint64_t index_id_; // index_id
|
|
ObTableMetaInfo *table_meta_info_; // table related meta info
|
|
ObIndexMetaInfo index_meta_info_; // index related meta info
|
|
bool is_virtual_table_; // is virtual table
|
|
bool is_unique_; // whether query range is unique
|
|
bool is_inner_path_;
|
|
bool can_use_batch_nlj_;
|
|
ObRangesArray ranges_; // all the ranges
|
|
ObRangesArray ss_ranges_; // skip scan ranges
|
|
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> range_columns_; // all the range columns
|
|
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> access_column_items_; // all the access columns
|
|
common::ObSEArray<ColumnItem, 4, common::ModulePageAllocator, true> index_access_column_items_; // all the access columns
|
|
|
|
//这几个filter的分类参考OptimizerUtil::classify_filters()
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> prefix_filters_; // filters match index prefix
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> pushdown_prefix_filters_; // filters match index prefix along pushed down filter
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> ss_postfix_range_filters_; // range conditions extract postfix range for skip scan
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> postfix_filters_; // filters evaluated before index back, but not index prefix
|
|
common::ObSEArray<ObRawExpr *, 4, common::ModulePageAllocator, true> table_filters_; // filters evaluated after index back
|
|
|
|
common::ObSEArray<uint64_t, 4, common::ModulePageAllocator, true> access_columns_;
|
|
|
|
OptTableMetas *table_metas_;
|
|
OptSelectivityCtx *sel_ctx_;
|
|
// the following information are useful when estimating cost
|
|
ObBaseTableEstMethod est_method_;
|
|
double prefix_filter_sel_;
|
|
double pushdown_prefix_filter_sel_;
|
|
double postfix_filter_sel_;
|
|
double table_filter_sel_;
|
|
double join_filter_sel_;
|
|
double ss_prefix_ndv_; // skip scan prefix columns NDV
|
|
double ss_postfix_range_filters_sel_;
|
|
double logical_query_range_row_count_;// 估计出的抽出的query range中所包含的行数(logical)
|
|
double phy_query_range_row_count_;// 估计出的抽出的query range中所包含的行数(physical)
|
|
double index_back_row_count_;// 估计出的需要回表的行数
|
|
double output_row_count_;
|
|
common::ObSimpleBatch::ObBatchType batch_type_;
|
|
SampleInfo sample_info_;
|
|
bool use_column_store_;
|
|
bool at_most_one_range_;
|
|
bool index_back_with_column_store_;
|
|
common::ObSEArray<ObCostColumnGroupInfo, 4, common::ModulePageAllocator, true> index_scan_column_group_infos_;
|
|
common::ObSEArray<ObCostColumnGroupInfo, 4, common::ModulePageAllocator, true> index_back_column_group_infos_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObCostTableScanInfo);
|
|
};
|
|
|
|
struct ObCostBaseJoinInfo : public ObTwoNodeCostInfo
|
|
{
|
|
ObCostBaseJoinInfo(double left_rows, double left_width,
|
|
double right_rows, double right_width,
|
|
ObRelIds left_ids, ObRelIds right_ids, ObJoinType join_type,
|
|
const common::ObIArray<ObRawExpr *> &equal_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &other_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &filters,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: ObTwoNodeCostInfo(left_rows, left_width,
|
|
right_rows, right_width,
|
|
table_metas, sel_ctx),
|
|
left_ids_(left_ids),
|
|
right_ids_(right_ids),
|
|
join_type_(join_type),
|
|
equal_join_conditions_(equal_join_conditions),
|
|
other_join_conditions_(other_join_conditions),
|
|
filters_(filters)
|
|
{ }
|
|
virtual ~ObCostBaseJoinInfo() { };
|
|
|
|
TO_STRING_KV(K_(left_rows), K_(right_rows),
|
|
K_(left_width), K_(right_width),
|
|
K_(left_ids), K_(right_ids), K(join_type_),
|
|
K_(equal_join_conditions), K_(other_join_conditions));
|
|
ObRelIds left_ids_;
|
|
ObRelIds right_ids_;
|
|
ObJoinType join_type_;
|
|
const common::ObIArray<ObRawExpr*> &equal_join_conditions_;
|
|
const common::ObIArray<ObRawExpr*> &other_join_conditions_;
|
|
// for outer join, denote where condition
|
|
const common::ObIArray<ObRawExpr*> &filters_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObCostBaseJoinInfo);
|
|
};
|
|
|
|
struct ObCostNLJoinInfo : public ObCostBaseJoinInfo
|
|
{
|
|
ObCostNLJoinInfo(double left_rows, double left_cost, double left_width,
|
|
double right_rows, double right_cost, double right_width,
|
|
ObRelIds left_ids, ObRelIds right_ids, ObJoinType join_type,
|
|
double anti_or_semi_match_sel,
|
|
bool with_nl_param,
|
|
bool need_mat,
|
|
bool right_has_px_rescan,
|
|
int64_t parallel,
|
|
const common::ObIArray<ObRawExpr *> &equal_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &other_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &filters,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: ObCostBaseJoinInfo(left_rows, left_width,
|
|
right_rows, right_width,
|
|
left_ids, right_ids, join_type,
|
|
equal_join_conditions,
|
|
other_join_conditions,
|
|
filters,
|
|
table_metas,
|
|
sel_ctx),
|
|
left_cost_(left_cost),
|
|
right_cost_(right_cost),
|
|
anti_or_semi_match_sel_(anti_or_semi_match_sel),
|
|
parallel_(parallel),
|
|
with_nl_param_(with_nl_param),
|
|
need_mat_(need_mat),
|
|
right_has_px_rescan_(right_has_px_rescan)
|
|
{ }
|
|
virtual ~ObCostNLJoinInfo() { }
|
|
TO_STRING_KV(K_(left_rows), K_(left_cost), K_(right_rows), K_(right_cost),
|
|
K_(left_width), K_(right_width),
|
|
K_(left_ids), K_(right_ids), K_(join_type),
|
|
K_(with_nl_param), K_(need_mat), K_(right_has_px_rescan),
|
|
K_(equal_join_conditions), K_(other_join_conditions), K_(filters));
|
|
double left_cost_;
|
|
double right_cost_;
|
|
double anti_or_semi_match_sel_;
|
|
int64_t parallel_;
|
|
bool with_nl_param_;
|
|
bool need_mat_;
|
|
bool right_has_px_rescan_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObCostNLJoinInfo);
|
|
};
|
|
|
|
/**
|
|
* so far hash join info only contain variables from base class,
|
|
* in future, we will change cost model and may need additional information
|
|
*/
|
|
struct ObCostMergeJoinInfo : public ObCostBaseJoinInfo
|
|
{
|
|
ObCostMergeJoinInfo(double left_rows, double left_width,
|
|
double right_rows, double right_width,
|
|
ObRelIds left_ids, ObRelIds right_ids, ObJoinType join_type,
|
|
const common::ObIArray<ObRawExpr *> &equal_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &other_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &filters,
|
|
double equal_cond_sel, double other_cond_sel,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: ObCostBaseJoinInfo(left_rows, left_width,
|
|
right_rows, right_width,
|
|
left_ids, right_ids, join_type,
|
|
equal_join_conditions, other_join_conditions, filters,
|
|
table_metas, sel_ctx),
|
|
equal_cond_sel_(equal_cond_sel),
|
|
other_cond_sel_(other_cond_sel)
|
|
{ }
|
|
virtual ~ObCostMergeJoinInfo() { };
|
|
TO_STRING_KV(K_(left_rows), K_(right_rows),
|
|
K_(left_width), K_(right_width),
|
|
K_(left_ids), K_(right_ids), K_(join_type),
|
|
K_(equal_join_conditions), K_(other_join_conditions), K_(filters));
|
|
double equal_cond_sel_;
|
|
double other_cond_sel_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObCostMergeJoinInfo);
|
|
};
|
|
|
|
/**
|
|
* so far hash join info only contain variables from base class,
|
|
* in future, we will change cost model and may need additional information
|
|
*/
|
|
struct ObCostHashJoinInfo : public ObCostBaseJoinInfo
|
|
{
|
|
ObCostHashJoinInfo(double left_rows, double left_width,
|
|
double right_rows, double right_width,
|
|
ObRelIds left_ids, ObRelIds right_ids, ObJoinType join_type,
|
|
const common::ObIArray<ObRawExpr *> &equal_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &other_join_conditions,
|
|
const common::ObIArray<ObRawExpr *> &filters,
|
|
const ObIArray<JoinFilterInfo> &join_filter_infos,
|
|
double equal_cond_sel, double other_cond_sel,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: ObCostBaseJoinInfo(left_rows, left_width,
|
|
right_rows, right_width,
|
|
left_ids, right_ids, join_type,
|
|
equal_join_conditions, other_join_conditions, filters,
|
|
table_metas, sel_ctx),
|
|
join_filter_infos_(join_filter_infos),
|
|
equal_cond_sel_(equal_cond_sel),
|
|
other_cond_sel_(other_cond_sel)
|
|
{ };
|
|
TO_STRING_KV(K_(left_rows), K_(right_rows),
|
|
K_(left_width), K_(right_width),
|
|
K_(left_ids), K_(right_ids), K_(join_type),
|
|
K_(equal_join_conditions), K_(other_join_conditions), K_(filters));
|
|
virtual ~ObCostHashJoinInfo() { };
|
|
const ObIArray<JoinFilterInfo> &join_filter_infos_;
|
|
double equal_cond_sel_;
|
|
double other_cond_sel_;
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ObCostHashJoinInfo);
|
|
};
|
|
|
|
struct ObSubplanFilterCostInfo
|
|
{
|
|
ObSubplanFilterCostInfo(const ObIArray<ObBasicCostInfo> &children,
|
|
const ObBitSet<> &onetime_idxs,
|
|
const ObBitSet<> &initplan_idxs)
|
|
: children_(children), onetime_idxs_(onetime_idxs), initplan_idxs_(initplan_idxs)
|
|
{ }
|
|
TO_STRING_KV(K_(children), K_(onetime_idxs), K_(initplan_idxs));
|
|
|
|
const ObIArray<ObBasicCostInfo> &children_;
|
|
const ObBitSet<> &onetime_idxs_;
|
|
const ObBitSet<> &initplan_idxs_;
|
|
};
|
|
|
|
struct ObCostMergeSetInfo
|
|
{
|
|
ObCostMergeSetInfo(const ObIArray<ObBasicCostInfo> &children,
|
|
int64_t op, int64_t num_select_items)
|
|
: children_(children), op_(op), num_select_items_(num_select_items){}
|
|
|
|
const ObIArray<ObBasicCostInfo> &children_;
|
|
int64_t op_;
|
|
int64_t num_select_items_;
|
|
};
|
|
|
|
struct ObCostHashSetInfo : public ObTwoNodeCostInfo
|
|
{
|
|
ObCostHashSetInfo(double left_rows,
|
|
double left_width,
|
|
double right_rows,
|
|
double right_width,
|
|
int64_t op,
|
|
const ObIArray<ObRawExpr *> &hash_columns,
|
|
OptTableMetas *table_metas, OptSelectivityCtx *sel_ctx)
|
|
: ObTwoNodeCostInfo(
|
|
left_rows,
|
|
left_width,
|
|
right_rows,
|
|
right_width,
|
|
table_metas,
|
|
sel_ctx),
|
|
op_(op),
|
|
hash_columns_(hash_columns) {}
|
|
|
|
int64_t op_;
|
|
const ObIArray<ObRawExpr *> &hash_columns_;
|
|
};
|
|
|
|
struct ObSortCostInfo
|
|
{
|
|
ObSortCostInfo(double rows,
|
|
double width,
|
|
int64_t prefix_pos,
|
|
const ObIArray<OrderItem> &order_items,
|
|
const bool is_local_order,
|
|
OptTableMetas *table_metas = NULL,
|
|
OptSelectivityCtx *sel_ctx = NULL,
|
|
double topn = -1,
|
|
int64_t part_cnt = 0)
|
|
: rows_(rows),
|
|
width_(width),
|
|
prefix_pos_(prefix_pos),
|
|
order_items_(order_items),
|
|
is_local_merge_sort_(is_local_order),
|
|
table_metas_(table_metas),
|
|
sel_ctx_(sel_ctx),
|
|
topn_(topn),
|
|
part_cnt_(part_cnt)
|
|
{}
|
|
TO_STRING_KV(K_(rows), K_(width), K_(prefix_pos), K_(order_items),
|
|
K_(is_local_merge_sort), K_(topn), K_(part_cnt));
|
|
double rows_;
|
|
double width_;
|
|
// not prefix sort if prefix_pos_ <= 0
|
|
int64_t prefix_pos_;
|
|
const ObIArray<OrderItem> &order_items_;
|
|
bool is_local_merge_sort_;
|
|
// used to calculate ndv in prefix sort
|
|
OptTableMetas *table_metas_;
|
|
OptSelectivityCtx *sel_ctx_;
|
|
// not top-n sort if topn_ < 0
|
|
double topn_;
|
|
// not hash_based sort if part_cnt <= 0
|
|
int64_t part_cnt_;
|
|
};
|
|
|
|
struct ObDelUpCostInfo
|
|
{
|
|
ObDelUpCostInfo(double affect_rows,
|
|
double index_count,
|
|
double constraint_count)
|
|
:affect_rows_(affect_rows),
|
|
index_count_(index_count),
|
|
constraint_count_(constraint_count)
|
|
{}
|
|
|
|
TO_STRING_KV(
|
|
K_(affect_rows),
|
|
K_(index_count),
|
|
K_(constraint_count)
|
|
);
|
|
|
|
double affect_rows_;
|
|
double index_count_;
|
|
double constraint_count_;
|
|
};
|
|
|
|
struct ObExchCostInfo
|
|
{
|
|
ObExchCostInfo(double rows,
|
|
double width,
|
|
ObPQDistributeMethod::Type dist_method,
|
|
int64_t out_parallel,
|
|
int64_t in_parallel,
|
|
bool is_local_order,
|
|
const ObIArray<OrderItem> &sort_keys,
|
|
int64_t in_server_cnt)
|
|
: sort_keys_(sort_keys),
|
|
rows_(rows),
|
|
width_(width),
|
|
dist_method_(dist_method),
|
|
out_parallel_(out_parallel),
|
|
in_parallel_(in_parallel),
|
|
is_local_order_(is_local_order),
|
|
in_server_cnt_(in_server_cnt)
|
|
{ }
|
|
const ObIArray<OrderItem> &sort_keys_;
|
|
double rows_;
|
|
double width_;
|
|
ObPQDistributeMethod::Type dist_method_;
|
|
int64_t out_parallel_;
|
|
int64_t in_parallel_;
|
|
bool is_local_order_;
|
|
int64_t in_server_cnt_;
|
|
};
|
|
|
|
struct ObExchInCostInfo
|
|
{
|
|
ObExchInCostInfo(double rows,
|
|
double width,
|
|
ObPQDistributeMethod::Type dist_method,
|
|
int64_t parallel,
|
|
int64_t server_cnt,
|
|
bool is_local_order,
|
|
const ObIArray<OrderItem> &sort_keys)
|
|
: sort_keys_(sort_keys),
|
|
rows_(rows),
|
|
width_(width),
|
|
dist_method_(dist_method),
|
|
parallel_(parallel),
|
|
server_cnt_(server_cnt),
|
|
is_local_order_(is_local_order)
|
|
{}
|
|
const ObIArray<OrderItem> &sort_keys_;
|
|
double rows_;
|
|
double width_;
|
|
ObPQDistributeMethod::Type dist_method_;
|
|
int64_t parallel_;
|
|
int64_t server_cnt_;
|
|
bool is_local_order_;
|
|
};
|
|
|
|
struct ObExchOutCostInfo
|
|
{
|
|
ObExchOutCostInfo(double rows,
|
|
double width,
|
|
ObPQDistributeMethod::Type dist_method,
|
|
int64_t parallel,
|
|
int64_t server_cnt)
|
|
: rows_(rows),
|
|
width_(width),
|
|
dist_method_(dist_method),
|
|
parallel_(parallel),
|
|
server_cnt_(server_cnt)
|
|
{}
|
|
double rows_;
|
|
double width_;
|
|
ObPQDistributeMethod::Type dist_method_;
|
|
int64_t parallel_;
|
|
int64_t server_cnt_;
|
|
};
|
|
|
|
class ObOptEstCostModel
|
|
{
|
|
public:
|
|
const static int64_t DEFAULT_LOCAL_ORDER_DEGREE;
|
|
const static int64_t DEFAULT_MAX_STRING_WIDTH;
|
|
const static int64_t DEFAULT_FIXED_OBJ_WIDTH;
|
|
|
|
ObOptEstCostModel(const ObOptCostModelParameter &cost_params,
|
|
const OptSystemStat &stat)
|
|
:cost_params_(cost_params),
|
|
sys_stat_(stat)
|
|
{}
|
|
|
|
virtual ~ObOptEstCostModel()=default;
|
|
|
|
int cost_nestloop(const ObCostNLJoinInfo &est_cost_info,
|
|
double &cost,
|
|
double &filter_selectivity,
|
|
common::ObIArray<ObExprSelPair> &all_predicate_sel);
|
|
|
|
int cost_mergejoin(const ObCostMergeJoinInfo &est_cost_info,
|
|
double &cost);
|
|
|
|
int cost_hashjoin(const ObCostHashJoinInfo &est_cost_info,
|
|
double &cost);
|
|
|
|
int cost_sort_and_exchange(OptTableMetas *table_metas,
|
|
OptSelectivityCtx *sel_ctx,
|
|
const ObPQDistributeMethod::Type dist_method,
|
|
const bool is_distributed,
|
|
const bool input_local_order,
|
|
const double input_card,
|
|
const double input_width,
|
|
const double input_cost,
|
|
const int64_t out_parallel,
|
|
const int64_t in_server_cnt,
|
|
const int64_t in_parallel,
|
|
const ObIArray<OrderItem> &expected_ordering,
|
|
const bool need_sort,
|
|
const int64_t prefix_pos,
|
|
double &cost);
|
|
|
|
// 对外提供两个估算排序算子代价的接口,一个使用ObRawExpr表示sort key,另一个使用
|
|
// OrderItem。
|
|
// 其它的参数信息通过cost_info传入,内部基于参数信息应该采用哪种排序
|
|
// 算法(目前包括普通排序、top-n 排序、前缀排序),对外暂不暴露实际排序算法的估算接口
|
|
int cost_sort(const ObSortCostInfo &cost_info,
|
|
double &cost);
|
|
|
|
int cost_exchange(const ObExchCostInfo &cost_info,
|
|
double &ex_cost);
|
|
|
|
int cost_exchange_in(const ObExchInCostInfo &cost_info,
|
|
double &cost);
|
|
|
|
int cost_exchange_out(const ObExchOutCostInfo &cost_info,
|
|
double &cost);
|
|
|
|
double cost_merge_group(double rows,
|
|
double res_rows,
|
|
double width,
|
|
const ObIArray<ObRawExpr *> &group_columns,
|
|
int64_t agg_col_count);
|
|
|
|
double cost_hash_group(double rows,
|
|
double res_rows,
|
|
double width,
|
|
const ObIArray<ObRawExpr *> &group_columns,
|
|
int64_t agg_col_count);
|
|
|
|
double cost_scalar_group(double rows,
|
|
int64_t agg_col_count);
|
|
|
|
double cost_merge_distinct(double rows,
|
|
double res_rows,
|
|
double width,
|
|
const ObIArray<ObRawExpr *> &distinct_columns);
|
|
|
|
double cost_hash_distinct(double rows,
|
|
double res_rows,
|
|
double width,
|
|
const ObIArray<ObRawExpr *> &disinct_columns);
|
|
|
|
double cost_get_rows(double rows);
|
|
|
|
double cost_sequence(double rows, double uniq_sequence_cnt);
|
|
|
|
double cost_material(const double rows, const double average_row_size);
|
|
|
|
double cost_read_materialized(const double rows);
|
|
|
|
double cost_filter_rows(double rows, ObIArray<ObRawExpr*> &filters);
|
|
|
|
int cost_subplan_filter(const ObSubplanFilterCostInfo &info, double &cost);
|
|
|
|
int cost_union_all(const ObCostMergeSetInfo &info, double &cost);
|
|
|
|
int cost_merge_set(const ObCostMergeSetInfo &info, double &cost);
|
|
|
|
int cost_hash_set(const ObCostHashSetInfo &info, double &cost);
|
|
|
|
int cost_project(double rows,
|
|
const ObIArray<ColumnItem> &columns,
|
|
bool is_get,
|
|
bool use_column_store,
|
|
double &cost);
|
|
|
|
int cost_project(double rows,
|
|
const ObIArray<ObRawExpr*> &columns,
|
|
bool is_get,
|
|
bool use_column_store,
|
|
double &cost);
|
|
|
|
int cost_full_table_scan_project(double rows,
|
|
const ObCostTableScanInfo &est_cost_info,
|
|
bool is_get,
|
|
double &cost);
|
|
|
|
double cost_quals(double rows, const ObIArray<ObRawExpr *> &quals, bool need_scale = true);
|
|
|
|
double cost_hash(double rows, const ObIArray<ObRawExpr *> &hash_exprs);
|
|
|
|
double cost_late_materialization_table_get(int64_t column_cnt);
|
|
|
|
void cost_late_materialization_table_join(double left_card,
|
|
double left_cost,
|
|
double right_card,
|
|
double right_cost,
|
|
double &op_cost,
|
|
double &cost);
|
|
void cost_late_materialization(double left_card,
|
|
double left_cost,
|
|
int64_t column_count,
|
|
double &cost);
|
|
|
|
int get_sort_cmp_cost(const common::ObIArray<sql::ObExprResType> &types, double &cost);
|
|
|
|
int cost_window_function(double rows, double width, double win_func_cnt, double &cost);
|
|
|
|
int cost_insert(ObDelUpCostInfo& cost_info, double &cost);
|
|
|
|
int cost_update(ObDelUpCostInfo& cost_info, double &cost);
|
|
|
|
int cost_delete(ObDelUpCostInfo& cost_info, double &cost);
|
|
|
|
/*
|
|
* entry point for estimating table access cost
|
|
*/
|
|
int cost_table(const ObCostTableScanInfo &est_cost_info,
|
|
int64_t parallel,
|
|
double &cost);
|
|
|
|
int cost_table_for_parallel(const ObCostTableScanInfo &est_cost_info,
|
|
const int64_t parallel,
|
|
const double part_cnt_per_dop,
|
|
double &px_cost,
|
|
double &cost);
|
|
|
|
int cost_px(int64_t parallel, double &px_cost);
|
|
|
|
int calc_range_cost(const ObTableMetaInfo& table_meta_info,
|
|
const ObIArray<ObRawExpr *> &filters,
|
|
int64_t index_column_count,
|
|
int64_t range_count,
|
|
double range_sel,
|
|
double &cost);
|
|
int calc_pred_cost_per_row(const ObRawExpr *expr,
|
|
double card,
|
|
double &cost);
|
|
|
|
protected:
|
|
int cost_sort(const ObSortCostInfo &cost_info,
|
|
const common::ObIArray<ObExprResType> &order_col_types,
|
|
double &cost);
|
|
|
|
int cost_part_sort(const ObSortCostInfo &cost_info,
|
|
const ObIArray<ObRawExpr *> &order_exprs,
|
|
const ObIArray<ObExprResType> &order_col_types,
|
|
double &cost);
|
|
int cost_part_topn_sort(const ObSortCostInfo &cost_info,
|
|
const ObIArray<ObRawExpr *> &order_exprs,
|
|
const ObIArray<ObExprResType> &order_col_types,
|
|
double &cost);
|
|
|
|
int cost_prefix_sort(const ObSortCostInfo &cost_info,
|
|
const ObIArray<ObRawExpr *> &order_exprs,
|
|
const int64_t topn_count,
|
|
double &cost);
|
|
|
|
int cost_topn_sort(const ObSortCostInfo &cost_info,
|
|
const ObIArray<ObExprResType> &types,
|
|
double &cost);
|
|
|
|
int cost_local_order_sort(const ObSortCostInfo &cost_info,
|
|
const ObIArray<ObExprResType> &types,
|
|
double &cost);
|
|
|
|
int cost_topn_sort_inner(const ObIArray<ObExprResType> &types,
|
|
double rows,
|
|
double n,
|
|
double &cost);
|
|
|
|
//calculate real sort cost (std::sort)
|
|
int cost_sort_inner(const common::ObIArray<sql::ObExprResType> &types,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int cost_local_order_sort_inner(const common::ObIArray<sql::ObExprResType> &types,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
// estimate cost for non-virtual table
|
|
int cost_basic_table(const ObCostTableScanInfo &est_cost_info,
|
|
const double part_cnt_per_dop,
|
|
double &cost);
|
|
|
|
int cost_index_scan(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &prefix_filter_sel,
|
|
double &cost);
|
|
|
|
int cost_index_back(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &prefix_filter_sel,
|
|
double &cost);
|
|
|
|
int cost_column_store_index_scan(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &prefix_filter_sel,
|
|
double &cost);
|
|
|
|
int cost_column_store_index_back(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &prefix_filter_sel,
|
|
double &cost);
|
|
int cost_row_store_index_scan(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int cost_row_store_index_back(const ObCostTableScanInfo &est_cost_info,
|
|
double row_count,
|
|
double &cost);
|
|
// estimate the network transform and rpc cost for global index
|
|
int cost_global_index_back_with_rp(double row_count,
|
|
const ObCostTableScanInfo &est_cost_info,
|
|
double &cost);
|
|
|
|
int cost_range_scan(const ObCostTableScanInfo &est_cost_info,
|
|
bool is_scan_index,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int cost_range_get(const ObCostTableScanInfo &est_cost_info,
|
|
bool is_scan_index,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int range_get_io_cost(const ObCostTableScanInfo &est_cost_info,
|
|
bool is_scan_index,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int range_scan_io_cost(const ObCostTableScanInfo &est_cost_info,
|
|
bool is_scan_index,
|
|
double row_count,
|
|
double &cost);
|
|
|
|
int range_scan_cpu_cost(const ObCostTableScanInfo &est_cost_info,
|
|
bool is_scan_index,
|
|
double row_count,
|
|
bool is_get,
|
|
double &cost);
|
|
|
|
protected:
|
|
const ObOptCostModelParameter &cost_params_;
|
|
const OptSystemStat &sys_stat_;
|
|
DISALLOW_COPY_AND_ASSIGN(ObOptEstCostModel);
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
#endif /* OCEANBASE_SQL_OPTIMIZER_OB_OPT_EST_COST_MODEL_ */
|