fix optimizer stats and parser bug

This commit is contained in:
wangt1xiuyi
2023-05-25 18:41:19 +00:00
committed by ob-robot
parent 0557e597cb
commit 2ba249cddb
11 changed files with 98 additions and 35 deletions

View File

@ -2811,6 +2811,7 @@ int ObDbmsStats::set_table_prefs(sql::ObExecContext &ctx,
param.allocator_ = &ctx.get_allocator();
ObSEArray<uint64_t, 4> table_ids;
ObStatPrefs *stat_pref = NULL;
bool use_size_auto = false;
if (OB_FAIL(check_statistic_table_writeable(ctx))) {
LOG_WARN("failed to check tenant is restore", K(ret));
} else if (OB_FAIL(parse_table_part_info(ctx, params.at(0), params.at(1), dummy_param, param))) {
@ -2841,7 +2842,7 @@ int ObDbmsStats::set_table_prefs(sql::ObExecContext &ctx,
} else if (OB_FAIL(stat_pref->dump_pref_name_and_value(opt_name, opt_value))) {
LOG_WARN("failed to dump pref name and value");
} else if (0 == opt_name.case_compare("METHOD_OPT") &&
OB_FAIL(parse_method_opt(ctx, param.allocator_, param.column_params_, opt_value))) {
OB_FAIL(parse_method_opt(ctx, param.allocator_, param.column_params_, opt_value, use_size_auto))) {
LOG_WARN("failed to parse method opt", K(ret));
} else if (OB_FAIL(ObDbmsStatsPreferences::set_prefs(ctx, table_ids, opt_name, opt_value))) {
LOG_WARN("failed to set prefs", K(ret));
@ -3995,14 +3996,12 @@ int ObDbmsStats::parse_granularity_and_method_opt(ObExecContext &ctx,
int ret = OB_SUCCESS;
//virtual table(not include real agent table) doesn't gather histogram.
bool is_vt = is_virtual_table(param.table_id_);
ObGranularityType granu_type = ObGranularityType::GRANULARITY_INVALID;
if (OB_FAIL(ObDbmsStatsUtils::parse_granularity(param.granularity_, granu_type))) {
LOG_WARN("failed to parse granularity");
} else if (OB_FAIL(resovle_granularity(granu_type, param))) {
LOG_WARN("failed to resovle granularity", K(granu_type));
} else if (0 == param.method_opt_.case_compare("Z") && !is_vt) {
bool use_size_auto = false;
if (0 == param.method_opt_.case_compare("Z") && !is_vt) {
if (OB_FAIL(set_default_column_params(param.column_params_))) {
LOG_WARN("failed to set default column params", K(ret));
} else {
use_size_auto = true;
}
} else {
// method_opt => null, do not gather histogram, gather basic column stat
@ -4011,12 +4010,19 @@ int ObDbmsStats::parse_granularity_and_method_opt(ObExecContext &ctx,
param.method_opt_.assign_ptr(method_opt_str, strlen(method_opt_str));
}
if (OB_FAIL(ObDbmsStats::parse_method_opt(ctx, param.allocator_,
param.column_params_, param.method_opt_))) {
param.column_params_,
param.method_opt_,
use_size_auto))) {
LOG_WARN("failed to parse method opt", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(process_not_size_manual_column(ctx, param))) {
ObGranularityType granu_type = ObGranularityType::GRANULARITY_INVALID;
if (OB_FAIL(ObDbmsStatsUtils::parse_granularity(param.granularity_, granu_type))) {
LOG_WARN("failed to parse granularity");
} else if (OB_FAIL(resovle_granularity(granu_type, use_size_auto, param))) {
LOG_WARN("failed to resovle granularity", K(granu_type));
} else if (OB_FAIL(process_not_size_manual_column(ctx, param))) {
LOG_WARN("failed to process not size manual column", K(ret));
}
}
@ -4168,9 +4174,11 @@ int ObDbmsStats::parse_set_column_stats_options(ObExecContext &ctx,
int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx,
ObIAllocator *allocator,
ObIArray<ObColumnStatParam> &column_params,
const ObString &method_opt)
const ObString &method_opt,
bool &use_size_auto)
{
int ret = OB_SUCCESS;
use_size_auto = false;
if (OB_ISNULL(allocator) || OB_ISNULL(ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(allocator), K(ctx.get_my_session()));
@ -4200,7 +4208,7 @@ int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(child_node));
} else if (T_FOR_ALL == child_node->type_) {
if (OB_FAIL(parser_for_all_clause(child_node, column_params))) {
if (OB_FAIL(parser_for_all_clause(child_node, column_params, use_size_auto))) {
LOG_WARN("failed to parser for all clause", K(ret));
} else {/*do nothing*/}
} else if (T_FOR_COLUMNS == child_node->type_) {
@ -4217,9 +4225,11 @@ int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx,
}
int ObDbmsStats::parser_for_all_clause(const ParseNode *for_all_node,
ObIArray<ObColumnStatParam> &column_params)
ObIArray<ObColumnStatParam> &column_params,
bool &use_size_auto)
{
int ret = OB_SUCCESS;
use_size_auto = false;
if (OB_ISNULL(for_all_node) || OB_UNLIKELY(for_all_node->type_ != T_FOR_ALL)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("get invalid argument", K(for_all_node), K(ret));
@ -4243,6 +4253,8 @@ int ObDbmsStats::parser_for_all_clause(const ParseNode *for_all_node,
if (OB_SUCC(ret) && NULL != for_all_node->children_[1]) {
if (OB_FAIL(parse_size_clause(for_all_node->children_[1], size_conf))) {
LOG_WARN("failed to parse size clause", K(ret));
} else {
use_size_auto = size_conf.is_auto();
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < column_params.count(); ++i) {
@ -6054,7 +6066,9 @@ bool ObDbmsStats::need_gather_index_stats(const ObTableStatParam &param)
*
* @return
*/
int ObDbmsStats::resovle_granularity(ObGranularityType granu_type, ObTableStatParam &param)
int ObDbmsStats::resovle_granularity(ObGranularityType granu_type,
const bool use_size_auto,
ObTableStatParam &param)
{
int ret = OB_SUCCESS;
if (ObGranularityType::GRANULARITY_AUTO == granu_type) {
@ -6064,7 +6078,7 @@ int ObDbmsStats::resovle_granularity(ObGranularityType granu_type, ObTableStatPa
// refine auto granularity based on subpart type
if (ObPartitionLevel::PARTITION_LEVEL_TWO == param.part_level_ &&
!(is_range_part(param.subpart_stat_param_.part_type_) || is_list_part(param.subpart_stat_param_.part_type_))) {
param.subpart_stat_param_.gather_histogram_ = false;
param.subpart_stat_param_.gather_histogram_ = !use_size_auto;
}
} else if (ObGranularityType::GRANULARITY_ALL == granu_type) {
param.global_stat_param_.set_gather_stat(false);

View File

@ -240,10 +240,12 @@ public:
static int parse_method_opt(sql::ObExecContext &ctx,
ObIAllocator *allocator,
ObIArray<ObColumnStatParam> &column_params,
const ObString &method_opt);
const ObString &method_opt,
bool &use_size_auto);
static int parser_for_all_clause(const ParseNode *for_all_node,
ObIArray<ObColumnStatParam> &column_params);
ObIArray<ObColumnStatParam> &column_params,
bool &use_size_auto);
static int parser_for_columns_clause(const ParseNode *for_col_node,
ObIArray<ObColumnStatParam> &column_params,
@ -549,9 +551,13 @@ private:
static bool is_func_index(const ObTableStatParam &index_param);
static bool need_gather_index_stats(const ObTableStatParam &table_param);
static int resovle_granularity(ObGranularityType granu_type, ObTableStatParam &param);
static int resovle_granularity(ObGranularityType granu_type,
const bool use_size_auto,
ObTableStatParam &param);
static void decide_modified_part(ObTableStatParam &param, const bool cascade_parts);
};

View File

@ -903,7 +903,11 @@ int ObOptStatSqlService::get_column_stat_sql(const uint64_t tenant_id,
char *llc_hex_buf = NULL;
int64_t llc_comp_size = 0;
int64_t llc_hex_size = 0;
if (OB_FAIL(get_valid_obj_str(stat.get_min_value(), min_meta, allocator, min_str, print_params)) ||
if (OB_UNLIKELY(ObHistType::INVALID_TYPE != stat.get_histogram().get_type() &&
stat.get_histogram().get_bucket_cnt() == 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(stat));
} else if (OB_FAIL(get_valid_obj_str(stat.get_min_value(), min_meta, allocator, min_str, print_params)) ||
OB_FAIL(get_valid_obj_str(stat.get_max_value(), max_meta, allocator, max_str, print_params))) {
LOG_WARN("failed to get valid obj str", K(stat.get_min_value()), K(stat.get_max_value()));
} else if (OB_FAIL(get_obj_binary_hex_str(stat.get_min_value(), allocator, b_min_str)) ||

View File

@ -14,6 +14,7 @@
#define OB_TOPK_HIST_ESTIMATOR_H
#include "share/stat/ob_stat_define.h"
#include "share/rc/ob_tenant_base.h"
namespace oceanbase
{
@ -53,13 +54,17 @@ class ObTopKFrequencyHistograms
used_list_(),
free_list_(),
topk_map_(),
topk_buf_(),
topk_buf_("OptTopkHist"),
use_first_alloc_(true),
obj_buf1_(),
obj_buf2_(),
obj_buf1_("OptTopkHist"),
obj_buf2_("OptTopkHist"),
copied_count_(),
need_deep_copy_(false)
{}
{
topk_buf_.set_tenant_id(MTL_ID());
obj_buf1_.set_tenant_id(MTL_ID());
obj_buf2_.set_tenant_id(MTL_ID());
}
int read_result(const ObObj &result_obj);

View File

@ -144,6 +144,7 @@ typedef struct _ParseNode
uint32_t is_multiset_ : 1; // for cast(multiset(...) as ...)
uint32_t is_forbid_anony_parameter_ : 1; // 1 表示禁止匿名块参数化
uint32_t is_input_quoted_ : 1; // indicate name_ob input whether with double quote
uint32_t is_forbid_parameter_ : 1; //1 indicate forbid parameter
uint32_t reserved_;
};
};

View File

@ -1011,7 +1011,7 @@ do {\
#define CHECK_MYSQL_COMMENT(p, node)\
do {\
if (p->mysql_compatible_comment_) {\
node->is_hidden_const_ = 1;\
node->is_forbid_parameter_ = 1;\
}\
} while(0);\

View File

@ -260,7 +260,8 @@ int ObSqlParameterization::is_fast_parse_const(TransformTreeCtx &ctx)
|| (T_IEEE754_INFINITE == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)
|| (T_IEEE754_NAN == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)
|| (T_SFU_INT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)
|| (T_FLOAT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)) {
|| (T_FLOAT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)
|| true == ctx.tree_->is_forbid_parameter_) {
ctx.is_fast_parse_const_ = false;
} else {
ctx.is_fast_parse_const_ = (IS_DATATYPE_OP(ctx.tree_->type_)

View File

@ -38,7 +38,8 @@ ObAnalyzeStmt::ObAnalyzeStmt()
is_drop_(false),
part_ids_(),
subpart_ids_(),
ref_table_type_(share::schema::ObTableType::MAX_TABLE_TYPE)
ref_table_type_(share::schema::ObTableType::MAX_TABLE_TYPE),
gather_subpart_hist_(false)
{
}
@ -98,6 +99,7 @@ int ObAnalyzeStmt::fill_table_stat_param(ObExecContext &ctx, common::ObTableStat
param.global_stat_param_.need_modify_ = partition_name_.empty();
param.part_stat_param_.need_modify_ = !partition_infos_.empty();
param.subpart_stat_param_.need_modify_ = !subpartition_infos_.empty();
param.subpart_stat_param_.gather_histogram_ = gather_subpart_hist_;
}
LOG_TRACE("link bug", K(param));

View File

@ -102,6 +102,8 @@ public:
int set_part_ids(ObIArray<int64_t> &part_ids);
int set_subpart_ids(ObIArray<int64_t> &subpart_ids);
void set_gather_subpart_hist(bool gather_subpart_hist) { gather_subpart_hist_ = gather_subpart_hist; }
TO_STRING_KV(K_(tenant_id),
K_(table_id),
@ -112,7 +114,9 @@ public:
K_(subpartition_infos),
K_(part_ids),
K_(subpart_ids),
K_(ref_table_type));
K_(ref_table_type),
K_(gather_subpart_hist));
private:
uint64_t tenant_id_;
ObString database_name_;
@ -141,6 +145,7 @@ private:
common::ObSEArray<PartInfo, 4, common::ModulePageAllocator, true> all_partition_infos_;
common::ObSEArray<PartInfo, 4, common::ModulePageAllocator, true> all_subpartition_infos_;
share::schema::ObTableType ref_table_type_;
bool gather_subpart_hist_;
DISALLOW_COPY_AND_ASSIGN(ObAnalyzeStmt);
};

View File

@ -91,14 +91,15 @@ int ObAnalyzeStmtResolver::resolve_oracle_analyze(const ParseNode &parse_node,
ParseNode *table_node = parse_node.children_[0];
ParseNode *part_node = parse_node.children_[1];
ParseNode *statistic_node = parse_node.children_[2];
bool is_hist_subpart = false;
if (OB_ISNULL(table_node) || OB_ISNULL(statistic_node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null parse node", K(table_node), K(statistic_node), K(ret));
} else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) {
LOG_WARN("failed to resolve table info", K(ret));
} else if (OB_FAIL(resolve_partition_info(part_node, analyze_stmt))) {
} else if (OB_FAIL(resolve_partition_info(part_node, analyze_stmt, is_hist_subpart))) {
LOG_WARN("failed to resolve partition info", K(ret));
} else if (OB_FAIL(resolve_statistic_info(statistic_node, analyze_stmt))) {
} else if (OB_FAIL(resolve_statistic_info(statistic_node, is_hist_subpart, analyze_stmt))) {
LOG_WARN("failed to resolve statistic info", K(ret));
} else { /*do nothing*/ }
}
@ -116,12 +117,13 @@ int ObAnalyzeStmtResolver::resolve_mysql_update_histogram(const ParseNode &parse
ParseNode *table_node = parse_node.children_[0];
ParseNode *column_node = parse_node.children_[1];
ParseNode *bucket_node = parse_node.children_[2];
bool dumy_bool = false;
if (OB_ISNULL(table_node) || OB_ISNULL(column_node) || OB_ISNULL(bucket_node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null parse node", K(table_node), K(column_node), K(bucket_node), K(ret));
} else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) {
LOG_WARN("failed to resolve table info", K(ret));
} else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt))) {
} else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt, dumy_bool))) {
LOG_WARN("failed to resolve partition info", K(ret));
} else if (OB_FAIL(resolve_mysql_column_bucket_info(column_node,
bucket_node->value_,
@ -148,12 +150,13 @@ int ObAnalyzeStmtResolver::resolve_mysql_delete_histogram(const ParseNode &parse
} else {
ParseNode *table_node = parse_node.children_[0];
ParseNode *column_node = parse_node.children_[1];
bool dumy_bool = false;
if (OB_ISNULL(table_node) || OB_ISNULL(column_node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null parse node", K(ret));
} else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) {
LOG_WARN("failed to resolve table info", K(ret));
} else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt))) {
} else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt, dumy_bool))) {
LOG_WARN("failed to resolve partition info", K(ret));
} else if (OB_FAIL(resolve_mysql_column_bucket_info(column_node, 0,
analyze_stmt))) {
@ -238,7 +241,8 @@ int ObAnalyzeStmtResolver::resolve_table_info(const ParseNode *table_node,
}
int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node,
ObAnalyzeStmt &analyze_stmt)
ObAnalyzeStmt &analyze_stmt,
bool &is_hist_subpart)
{
int ret = OB_SUCCESS;
const ObTableSchema *table_schema = NULL;
@ -248,6 +252,7 @@ int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node,
ObSEArray<int64_t, 4> part_ids;
ObSEArray<int64_t, 4> subpart_ids;
bool is_subpart_name = false;
is_hist_subpart = false;
ObString &partition_name = analyze_stmt.get_partition_name();
if (OB_ISNULL(schema_checker_)) {
@ -310,10 +315,15 @@ int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node,
}
}
}
if (OB_SUCC(ret) && share::schema::ObPartitionLevel::PARTITION_LEVEL_TWO == table_schema->get_part_level()) {
is_hist_subpart = (is_range_part(table_schema->get_sub_part_option().get_part_func_type()) ||
is_list_part(table_schema->get_sub_part_option().get_part_func_type()));
}
return ret;
}
int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt)
{
int ret = OB_SUCCESS;
@ -328,7 +338,7 @@ int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_nod
} else {
const ParseNode *for_clause_node = statistic_node->children_[0];
const ParseNode *sample_clause_node = statistic_node->children_[1];
if (OB_FAIL(resolve_for_clause_info(for_clause_node, analyze_stmt))) {
if (OB_FAIL(resolve_for_clause_info(for_clause_node, is_hist_subpart, analyze_stmt))) {
LOG_WARN("failed to resolve for clause info", K(ret));
} else if (OB_FAIL(resolve_sample_clause_info(sample_clause_node, analyze_stmt))) {
LOG_WARN("failed to resolve sample clause info", K(ret));
@ -338,6 +348,7 @@ int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_nod
}
int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt)
{
int ret = OB_SUCCESS;
@ -353,10 +364,13 @@ int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_n
} else if (NULL == for_clause_node) {
if (OB_FAIL(pl::ObDbmsStats::set_default_column_params(analyze_stmt.get_column_params()))) {
LOG_WARN("failed to set default column params", K(ret));
} else {
analyze_stmt.set_gather_subpart_hist(is_hist_subpart);
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < for_clause_node->num_child_; i++) {
if (OB_FAIL(resolve_for_clause_element(for_clause_node->children_[i],
is_hist_subpart,
analyze_stmt))) {
LOG_WARN("failed to resolve for clause element", K(ret));
} else { /*do nothing*/ }
@ -366,6 +380,7 @@ int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_n
}
int ObAnalyzeStmtResolver::resolve_for_clause_element(const ParseNode *for_clause_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt)
{
int ret = OB_SUCCESS;
@ -379,15 +394,21 @@ int ObAnalyzeStmtResolver::resolve_for_clause_element(const ParseNode *for_claus
LOG_WARN("analyze table not supported yet", K(ret));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "analyze table");
} else if (T_FOR_ALL == for_clause_node->type_) {
bool use_size_auto = false;
if (OB_FAIL(pl::ObDbmsStats::parser_for_all_clause(for_clause_node,
analyze_stmt.get_column_params()))) {
analyze_stmt.get_column_params(),
use_size_auto))) {
LOG_WARN("failed to resolve for all clause", K(ret));
} else {
analyze_stmt.set_gather_subpart_hist(!use_size_auto || (use_size_auto && is_hist_subpart));
}
} else if (T_FOR_COLUMNS == for_clause_node->type_) {
if (OB_FAIL(pl::ObDbmsStats::parser_for_columns_clause(for_clause_node,
analyze_stmt.get_column_params(),
all_for_col))) {
LOG_WARN("failed to parser for columns clause", K(ret));
} else {
analyze_stmt.set_gather_subpart_hist(true);
}
} else {
ret = OB_ERR_UNEXPECTED;

View File

@ -41,12 +41,16 @@ private:
int resolve_table_info(const ParseNode *table_node,
ObAnalyzeStmt &analyze_stmt);
int resolve_partition_info(const ParseNode *part_node,
ObAnalyzeStmt &analyze_stmt);
ObAnalyzeStmt &analyze_stmt,
bool &is_hist_subpart);
int resolve_statistic_info(const ParseNode *statistic_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt);
int resolve_for_clause_info(const ParseNode *for_clause_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt);
int resolve_for_clause_element(const ParseNode *for_clause_node,
const bool is_hist_subpart,
ObAnalyzeStmt &analyze_stmt);
int resolve_sample_clause_info(const ParseNode *sample_clause_node,
ObAnalyzeStmt &analyze_stmt);