[CP] fix some optimizer stats bug

This commit is contained in:
wangt1xiuyi 2024-04-08 07:24:46 +00:00 committed by ob-robot
parent 648c9b98b5
commit 73cc1ad061
7 changed files with 116 additions and 75 deletions

View File

@ -421,21 +421,26 @@ int ObDbmsStats::fast_gather_index_stats(ObExecContext &ctx,
{
int ret = OB_SUCCESS;
is_all_fast_gather = true;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_;
if (OB_FAIL(get_table_index_infos(ctx, data_param.table_id_, simple_index_infos))) {
if (OB_FAIL(get_table_index_infos(schema_guard,
ctx.get_my_session()->get_effective_tenant_id(),
data_param.table_id_,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) {
StatTable stat_table;
stat_table.database_id_ = data_param.db_id_;
stat_table.table_id_ = simple_index_infos.at(i).table_id_;
stat_table.table_id_ = index_tids[i];
ObTableStatParam index_param;
index_param.is_index_stat_ = true;
index_param.assign_common_property(data_param);
bool is_fast_gather = true;
const share::schema::ObTableSchema *index_schema = NULL;
if (simple_index_infos.at(i).table_id_ == data_param.table_id_) {
if (index_tids[i] == data_param.table_id_) {
//do nothing, remove primary table
} else if (OB_FAIL(parse_table_part_info(ctx, stat_table, index_param))) {
LOG_WARN("failed to parse table part info", K(ret));
@ -1072,17 +1077,22 @@ int ObDbmsStats::delete_table_index_stats(sql::ObExecContext &ctx,
const ObTableStatParam data_param)
{
int ret = OB_SUCCESS;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
if (OB_FAIL(get_table_index_infos(ctx, data_param.table_id_, simple_index_infos))) {
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
if (OB_FAIL(get_table_index_infos(ctx.get_virtual_table_ctx().schema_guard_,
ctx.get_my_session()->get_effective_tenant_id(),
data_param.table_id_,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) {
StatTable stat_table;
stat_table.database_id_ = data_param.db_id_;
stat_table.table_id_ = simple_index_infos.at(i).table_id_;
stat_table.table_id_ = index_tids[i];
ObTableStatParam index_param;
index_param.assign_common_property(data_param);
if (simple_index_infos.at(i).table_id_ == data_param.table_id_) {
if (index_tids[i] == data_param.table_id_) {
//do nothing, remove primary table
} else if (OB_FAIL(parse_table_part_info(ctx, stat_table, index_param))) {
LOG_WARN("failed to parse table part info", K(ret));
@ -1544,17 +1554,22 @@ int ObDbmsStats::export_table_index_stats(sql::ObExecContext &ctx,
const ObTableStatParam data_param)
{
int ret = OB_SUCCESS;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
if (OB_FAIL(get_table_index_infos(ctx, data_param.table_id_, simple_index_infos))) {
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
if (OB_FAIL(get_table_index_infos(ctx.get_virtual_table_ctx().schema_guard_,
ctx.get_my_session()->get_effective_tenant_id(),
data_param.table_id_,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) {
StatTable stat_table;
stat_table.database_id_ = data_param.db_id_;
stat_table.table_id_ = simple_index_infos.at(i).table_id_;
stat_table.table_id_ = index_tids[i];
ObTableStatParam index_param;
index_param.assign_common_property(data_param);
if (simple_index_infos.at(i).table_id_ == data_param.table_id_) {
if (index_tids[i] == data_param.table_id_) {
//do nothing, remove primary table
} else if (OB_FAIL(parse_table_part_info(ctx, stat_table, index_param))) {
LOG_WARN("failed to parse table part info", K(ret));
@ -1930,17 +1945,22 @@ int ObDbmsStats::import_table_index_stats(sql::ObExecContext &ctx,
const ObTableStatParam data_param)
{
int ret = OB_SUCCESS;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
if (OB_FAIL(get_table_index_infos(ctx, data_param.table_id_, simple_index_infos))) {
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
if (OB_FAIL(get_table_index_infos(ctx.get_virtual_table_ctx().schema_guard_,
ctx.get_my_session()->get_effective_tenant_id(),
data_param.table_id_,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) {
StatTable stat_table;
stat_table.database_id_ = data_param.db_id_;
stat_table.table_id_ = simple_index_infos.at(i).table_id_;
stat_table.table_id_ = index_tids[i];
ObTableStatParam index_param;
index_param.assign_common_property(data_param);
if (simple_index_infos.at(i).table_id_ == data_param.table_id_) {
if (index_tids[i] == data_param.table_id_) {
//do nothing, remove primary table
} else if (OB_FAIL(parse_table_part_info(ctx, stat_table, index_param))) {
LOG_WARN("failed to parse table part info", K(ret));
@ -2141,17 +2161,22 @@ int ObDbmsStats::lock_or_unlock_index_stats(sql::ObExecContext &ctx,
bool is_lock_stats)
{
int ret = OB_SUCCESS;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
if (OB_FAIL(get_table_index_infos(ctx, data_param.table_id_, simple_index_infos))) {
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
if (OB_FAIL(get_table_index_infos(ctx.get_virtual_table_ctx().schema_guard_,
ctx.get_my_session()->get_effective_tenant_id(),
data_param.table_id_,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) {
StatTable stat_table;
stat_table.database_id_ = data_param.db_id_;
stat_table.table_id_ = simple_index_infos.at(i).table_id_;
stat_table.table_id_ = index_tids[i];
ObTableStatParam index_param;
index_param.assign_common_property(data_param);
if (simple_index_infos.at(i).table_id_ == data_param.table_id_) {
if (index_tids[i] == data_param.table_id_) {
//do nothing, remove primary table
} else if (OB_FAIL(parse_table_part_info(ctx, stat_table, index_param))) {
LOG_WARN("failed to parse table part info", K(ret));
@ -5340,6 +5365,7 @@ int ObDbmsStats::gather_database_stats_job_proc(sql::ObExecContext &ctx,
int64_t duration_time = -1;
int64_t succeed_cnt = 0;
bool no_auto_gather = (OB_E(EventTable::EN_LEADER_STORAGE_ESTIMATION) OB_SUCCESS) != OB_SUCCESS;
ObSQLSessionInfo::LockGuard query_lock_guard(ctx.get_my_session()->get_query_lock());
if (OB_FAIL(check_statistic_table_writeable(ctx))) {
ret = OB_SUCCESS;
LOG_INFO("auto gather database statistics abort because of statistic table is unwriteable");
@ -5925,30 +5951,26 @@ bool ObDbmsStats::is_table_gather_global_stats(const int64_t global_id,
return is_gather;
}
int ObDbmsStats::get_table_index_infos(sql::ObExecContext &ctx,
const int64_t table_id,
ObIArray<ObAuxTableMetaInfo> &index_infos)
int ObDbmsStats::get_table_index_infos(share::schema::ObSchemaGetterGuard *schema_guard,
const uint64_t tenant_id,
const uint64_t table_id,
uint64_t *index_tid_arr,
int64_t &index_count)
{
int ret = OB_SUCCESS;
const share::schema::ObTableSchema *table_schema = NULL;
share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_;
if (OB_ISNULL(schema_guard)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(schema_guard));
} else if (OB_FAIL(schema_guard->get_table_schema(
ctx.get_my_session()->get_effective_tenant_id(),
table_id,
table_schema))) {
LOG_WARN("failed to get table schema", K(ret));
} else if (OB_ISNULL(table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(table_schema));
} else if (share::is_oracle_mapping_real_virtual_table(table_schema->get_table_id())) {
} else if (share::is_oracle_mapping_real_virtual_table(table_id)) {
// do not gather stat for oracle inner table index
} else if (OB_FAIL(table_schema->get_simple_index_infos(index_infos))) {
LOG_WARN("failed to get simple index infos", K(ret));
} else {
LOG_TRACE("Succeed to get table index infos", K(table_id), K(index_infos));
} else if (OB_FAIL(schema_guard->get_can_read_index_array(tenant_id,
table_id,
index_tid_arr,
index_count,
false, /*with_mv*/
true, /*with_global_index*/
false /*domain index*/))) {
LOG_WARN("failed to get can read index", K(ret));
}
return ret;
}
@ -5963,22 +5985,27 @@ int ObDbmsStats::get_index_schema(sql::ObExecContext &ctx,
int ret = OB_SUCCESS;
share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_;
index_schema = NULL;
ObSEArray<ObAuxTableMetaInfo, 4> simple_index_infos;
uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 1];
int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1;
if (OB_ISNULL(schema_guard)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(get_table_index_infos(ctx, data_table_id, simple_index_infos))) {
} else if (OB_FAIL(get_table_index_infos(ctx.get_virtual_table_ctx().schema_guard_,
ctx.get_my_session()->get_effective_tenant_id(),
data_table_id,
index_tids,
index_count))) {
LOG_WARN("failed to get table index infos", K(ret));
} else {
bool found_it = false;
for (int64_t i = 0; OB_SUCC(ret) && !found_it && i < simple_index_infos.count(); ++i) {
for (int64_t i = 0; OB_SUCC(ret) && !found_it && i < index_count; ++i) {
const share::schema::ObTableSchema *cur_index_schema = NULL;
ObString cur_index_name;
if (simple_index_infos.at(i).table_id_ == data_table_id) {
if (index_tids[i] == data_table_id) {
//do nothing, remove primary table
} else if (OB_FAIL(schema_guard->get_table_schema(
ctx.get_my_session()->get_effective_tenant_id(),
simple_index_infos.at(i).table_id_, cur_index_schema))) {
index_tids[i], cur_index_schema))) {
LOG_WARN("failed to get table schema", K(ret));
} else if (OB_ISNULL(cur_index_schema) || OB_UNLIKELY(!cur_index_schema->is_index_table())) {
ret = OB_ERR_UNEXPECTED;

View File

@ -579,9 +579,11 @@ private:
const ObObjParam &table_name,
ObTableStatParam &param);
static int get_table_index_infos(sql::ObExecContext &ctx,
const int64_t table_id,
ObIArray<ObAuxTableMetaInfo> &index_infos);
static int get_table_index_infos(share::schema::ObSchemaGetterGuard *schema_guard,
const uint64_t tenant_id,
const uint64_t table_id,
uint64_t *index_tid_arr,
int64_t &index_count);
static int get_table_partition_infos(const ObTableSchema &table_schema,
ObIAllocator &allocator,

View File

@ -315,14 +315,22 @@ int ObBasicStatsEstimator::do_estimate_block_count(ObExecContext &ctx,
{
int ret = OB_SUCCESS;
int64_t retry_cnt = 0;
const int64_t MAX_RETRY_CNT = 10;
do {
if (OB_FAIL(do_estimate_block_count_and_row_count(ctx, tenant_id, table_id, tablet_ids,
partition_ids, column_group_ids, estimate_res))) {
DAS_CTX(ctx).get_location_router().refresh_location_cache_by_errno(true, ret);
++ retry_cnt;
if (OB_FAIL(THIS_WORKER.check_status())) {
LOG_WARN("failed to check status", K(ret));
} else if (OB_FAIL(do_estimate_block_count_and_row_count(ctx, tenant_id, table_id, tablet_ids,
partition_ids, column_group_ids, estimate_res))) {
LOG_WARN("failed to do estimate block count and row count", K(ret));
if (DAS_CTX(ctx).get_location_router().is_refresh_location_error(ret)) {
DAS_CTX(ctx).get_location_router().refresh_location_cache_by_errno(true, ret);
++ retry_cnt;
ob_usleep(1000L * 1000L); // retry interval 1s
} else {
retry_cnt = MAX_RETRY_CNT;
}
}
} while (OB_FAIL(ret) && retry_cnt < 2);//retry one time if failed to estimate.
} while (OB_FAIL(ret) && retry_cnt < MAX_RETRY_CNT);
return ret;
}

View File

@ -1143,15 +1143,20 @@ OB_NOINLINE int ObDASLocationRouter::get_vt_ls_location(uint64_t table_id,
return ret;
}
bool ObDASLocationRouter::is_refresh_location_error(int err_no) const
{
return is_master_changed_error(err_no) ||
is_partition_change_error(err_no) ||
is_get_location_timeout_error(err_no) ||
is_server_down_error(err_no) ||
is_has_no_readable_replica_err(err_no) ||
is_unit_migrate(err_no);
}
void ObDASLocationRouter::refresh_location_cache_by_errno(bool is_nonblock, int err_no)
{
NG_TRACE_TIMES(1, get_location_cache_begin);
if (is_master_changed_error(err_no)
|| is_partition_change_error(err_no)
|| is_get_location_timeout_error(err_no)
|| is_server_down_error(err_no)
|| is_has_no_readable_replica_err(err_no)
|| is_unit_migrate(err_no)) {
if (is_refresh_location_error(err_no)) {
// Refresh tablet ls mapping and ls locations according to err_no.
//
// The timeout has been set inner the interface when renewing location synchronously.

View File

@ -331,6 +331,7 @@ public:
}
int save_success_task(const common::ObTabletID &succ_id)
{ return succ_tablet_list_.push_back(succ_id); }
bool is_refresh_location_error(int err_no) const;
TO_STRING_KV(K(all_tablet_list_));
private:
int get_vt_svr_pair(uint64_t vt_id, const VirtualSvrPair *&vt_svr_pair);

View File

@ -65,13 +65,16 @@ int ObAccessPathEstimation::inner_estimate_rowcount(ObOptimizerContext &ctx,
const bool is_inner_path,
const ObIArray<ObRawExpr*> &filter_exprs,
ObBaseTableEstMethod &method)
{
{
int ret = OB_SUCCESS;
ObBaseTableEstMethod valid_methods = 0;
ObBaseTableEstMethod hint_specify_methods = 0;
method = EST_INVALID;
if (OB_FAIL(get_valid_est_methods(ctx, paths, filter_exprs, is_inner_path, valid_methods))) {
if (OB_FAIL(get_valid_est_methods(ctx, paths, filter_exprs, is_inner_path, valid_methods, hint_specify_methods))) {
LOG_WARN("failed to get valid est methods", K(ret));
} else if (OB_FAIL(choose_best_est_method(ctx, paths, filter_exprs, valid_methods, method))) {
} else if (OB_FAIL(choose_best_est_method(ctx, paths, filter_exprs,
valid_methods & hint_specify_methods ? valid_methods & hint_specify_methods : valid_methods,
method))) {
LOG_WARN("failed to choose one est method", K(ret), K(valid_methods));
} else if (OB_FAIL(do_estimate_rowcount(ctx, paths, is_inner_path, filter_exprs, valid_methods, method))) {
LOG_WARN("failed to do estimate rowcount", K(ret), K(method), K(valid_methods));
@ -146,12 +149,13 @@ int ObAccessPathEstimation::get_valid_est_methods(ObOptimizerContext &ctx,
common::ObIArray<AccessPath*> &paths,
const ObIArray<ObRawExpr*> &filter_exprs,
bool is_inner_path,
ObBaseTableEstMethod &valid_methods)
ObBaseTableEstMethod &valid_methods,
ObBaseTableEstMethod &hint_specify_methods)
{
int ret = OB_SUCCESS;
valid_methods = EST_DEFAULT | EST_STAT | EST_STORAGE | EST_DS_BASIC | EST_DS_FULL;
hint_specify_methods = 0;
const ObBaseTableEstMethod EST_DS_METHODS = EST_DS_BASIC | EST_DS_FULL;
ObBaseTableEstMethod hint_specify_methods = 0;
const ObLogPlan* log_plan = NULL;
const OptTableMeta *table_meta = NULL;
if (OB_UNLIKELY(paths.empty()) ||
@ -218,13 +222,6 @@ int ObAccessPathEstimation::get_valid_est_methods(ObOptimizerContext &ctx,
LOG_WARN("failed to check dynamic sampling", K(ret));
}
// if there are any valid hint_specify_method, use it.
if (OB_SUCC(ret)) {
if (valid_methods & hint_specify_methods) {
valid_methods &= hint_specify_methods;
}
}
return ret;
}

View File

@ -76,7 +76,8 @@ private:
common::ObIArray<AccessPath*> &paths,
const ObIArray<ObRawExpr*> &filter_exprs,
bool is_inner_path,
ObBaseTableEstMethod &valid_methods);
ObBaseTableEstMethod &valid_methods,
ObBaseTableEstMethod &hint_specify_methods);
static int check_can_use_dynamic_sampling(ObOptimizerContext &ctx,
const ObLogPlan &log_plan,