/** * 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. */ #define USING_LOG_PREFIX COMMON #include "share/stat/ob_col_stat_sql_service.h" #include "lib/oblog/ob_log.h" #include "lib/oblog/ob_log_module.h" #include "lib/string/ob_sql_string.h" #include "lib/mysqlclient/ob_mysql_proxy.h" #include "lib/mysqlclient/ob_mysql_transaction.h" #include "lib/mysqlclient/ob_mysql_result.h" #include "lib/mysqlclient/ob_mysql_connection.h" #include "lib/mysqlclient/ob_mysql_statement.h" #include "lib/mysqlclient/ob_mysql_connection_pool.h" #include "lib/utility/ob_print_utils.h" #include "lib/compress/ob_compressor_pool.h" #include "common/ob_partition_key.h" #include "common/ob_timeout_ctx.h" #include "share/ob_dml_sql_splicer.h" #include "share/config/ob_server_config.h" #include "share/partition_table/ob_ipartition_table.h" #include "share/schema/ob_schema_utils.h" #include "share/schema/ob_multi_version_schema_service.h" #include "share/stat/ob_table_stat.h" #include "observer/ob_server_struct.h" #include "observer/ob_sql_client_decorator.h" #define MY_ALL_COL_STAT_COLUMN_NAME \ "tenant_id, " \ "table_id, " \ "partition_id, " \ "column_id, " \ "version, " \ "last_rebuild_version," \ "num_distinct, " \ "num_null," \ "min_value, " \ "max_value, " \ "llc_bitmap," \ "llc_bitmap_size " #define USER_TAB_COL_STATISTICS "__all_column_statistic" #define MY_FETCH_COL_STAT_SQL "SELECT " MY_ALL_COL_STAT_COLUMN_NAME " FROM " USER_TAB_COL_STATISTICS #define REPLACE_COL_STAT_SQL "REPLACE INTO " USER_TAB_COL_STATISTICS "(" MY_ALL_COL_STAT_COLUMN_NAME ") " #define MY_ALL_TABLE_STAT_COLUMN_NAME \ "tenant_id, " \ "table_id", \ "partition_id, " \ "partition_cnt, " \ "row_count, " \ "data_size," \ "data_version " #define DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(sql_client) \ const bool did_use_weak = false; \ const bool did_use_retry = false; \ const int64_t snapshot_timestamp = OB_INVALID_TIMESTAMP; \ const bool check_sys_variable = false; \ ObSQLClientRetryWeak sql_client_retry_weak( \ sql_client, did_use_weak, did_use_retry, snapshot_timestamp, check_sys_variable); namespace oceanbase { using namespace share; using namespace share::schema; namespace share { class ObIPartitiontable; } namespace common { const char* ObTableColStatSqlService::bitmap_compress_lib_name = "zlib_1.0"; ObTableColStatSqlService::ObTableColStatSqlService() : inited_(false), mysql_proxy_(NULL), config_(NULL) {} ObTableColStatSqlService::~ObTableColStatSqlService() {} int ObTableColStatSqlService::init(ObMySQLProxy* proxy, ObServerConfig* config) { int ret = OB_SUCCESS; lib::ObMutexGuard guard(mutex_); if (NULL == proxy) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "client proxy is null", K(ret)); } else if (inited_) { ret = OB_INIT_TWICE; COMMON_LOG(WARN, "sql service have already been initialized.", K(ret)); } else { mysql_proxy_ = proxy; config_ = config; inited_ = true; } return ret; } // init virtual table converter int ObTableColStatSqlService::init_vt_converter( uint64_t tenant_id, uint64_t ref_table_id, uint64_t column_id, ObStatConverterInfo& stat_converter_info) { int ret = OB_SUCCESS; ObSEArray column_ids; if (OB_FAIL(column_ids.push_back(column_id))) { LOG_WARN("failed to push back column ids", K(ret)); } else if (OB_FAIL(init_vt_converter(tenant_id, ref_table_id, column_ids, stat_converter_info))) { LOG_WARN("failed to init vt convert", K(ret)); } return ret; } int ObTableColStatSqlService::init_vt_converter( uint64_t tenant_id, uint64_t ref_table_id, ObStatConverterInfo& stat_converter_info) { int ret = OB_SUCCESS; ObArray column_ids; if (OB_FAIL(init_vt_converter(tenant_id, ref_table_id, column_ids, stat_converter_info))) { LOG_WARN("failed to init vt convert", K(ret)); } return ret; } int ObTableColStatSqlService::init_vt_converter(uint64_t tenant_id, uint64_t ref_table_id, const ObIArray& column_ids, ObStatConverterInfo& stat_converter_info) { int ret = OB_SUCCESS; const uint64_t real_table_id = ObSchemaUtils::get_real_table_mappings_tid(ref_table_id); if (OB_INVALID_ID == real_table_id) { } else { share::schema::ObSchemaGetterGuard schema_guard; const ObTableSchema* real_table_schema = NULL; const ObTableSchema* vt_table_schema = NULL; stat_converter_info.is_vt_mapping_ = true; stat_converter_info.real_table_id_ = real_table_id; bool has_column = (0 < column_ids.count()); if (!has_column) { } else if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_service is null", K(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, stat_converter_info.schema_guard_))) { LOG_WARN("fail to get schema guard", K(ret)); } else if (OB_FAIL(stat_converter_info.schema_guard_.get_table_schema( stat_converter_info.real_table_id_, real_table_schema))) { LOG_WARN("get table schema failed", K(stat_converter_info.real_table_id_), K(ret)); } else if (OB_FAIL(stat_converter_info.schema_guard_.get_table_schema(ref_table_id, vt_table_schema))) { LOG_WARN("get table schema failed", K(ref_table_id), K(ret)); } else if (OB_ISNULL(real_table_schema) || OB_ISNULL(vt_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema is null", KP(real_table_schema), KP(vt_table_schema), K(ret)); } else if (OB_FAIL(get_mapping_columns_info(vt_table_schema, real_table_schema, column_ids, stat_converter_info))) { LOG_WARN("failed to get mapping columns info", K(ret)); } else if (OB_FAIL(stat_converter_info.vt_result_converter_.init_without_allocator(stat_converter_info.col_schemas_, &stat_converter_info.output_column_with_tenant_ids_, tenant_id, stat_converter_info.tenant_id_col_id_, stat_converter_info.use_real_tenant_id_))) { LOG_WARN("failed to init converter", K(ret)); } if (OB_FAIL(ret)) { } else { LOG_DEBUG("debug virtual table stat", K(stat_converter_info.real_table_id_), K(tenant_id), K(column_ids), K(stat_converter_info.real_table_id_)); } } return ret; } int ObTableColStatSqlService::get_mapping_columns_info(const ObTableSchema* vt_table_schema, const ObTableSchema* real_table_schema, const ObIArray& column_ids, ObStatConverterInfo& stat_converter_info) { int ret = OB_SUCCESS; ObIArray& key_with_tenant_ids = stat_converter_info.output_column_with_tenant_ids_; OZ(key_with_tenant_ids.reserve(column_ids.count())); OZ(stat_converter_info.col_schemas_.reserve(column_ids.count())); OZ(stat_converter_info.real_column_ids_.reserve(column_ids.count())); OZ(stat_converter_info.column_ids_.assign(column_ids)); VTMapping* vt_mapping = nullptr; get_real_table_vt_mapping(vt_table_schema->get_table_id(), vt_mapping); if (OB_ISNULL(vt_mapping)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected status: vt mapping is null", K(ret), "table id", vt_table_schema->get_table_id()); } for (int64_t k = 0; k < column_ids.count() && OB_SUCC(ret); ++k) { uint64_t real_column_id = UINT64_MAX; uint64_t vt_column_id = column_ids.at(k); const ObColumnSchemaV2* vt_col_schema = vt_table_schema->get_column_schema(vt_column_id); if (OB_ISNULL(vt_col_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected status: column schema is null", K(vt_column_id), K(ret)); } for (int64_t nth_col = 0; nth_col < real_table_schema->get_column_count() && OB_SUCC(ret); ++nth_col) { const ObColumnSchemaV2* real_col_schema = real_table_schema->get_column_schema_by_idx(nth_col); if (OB_ISNULL(real_col_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column schema is null", K(ret), K(nth_col)); } else if (0 == real_col_schema->get_column_name_str().case_compare(vt_col_schema->get_column_name_str())) { real_column_id = real_col_schema->get_column_id(); bool extra_tenant_id = false; for (int64_t nth_i = vt_mapping->start_pos_; !extra_tenant_id && nth_i < vt_mapping->end_pos_ && OB_SUCC(ret); ++nth_i) { if (0 == ObString(with_tenant_id_columns[nth_i]).case_compare(vt_col_schema->get_column_name_str())) { extra_tenant_id = true; break; } } OZ(key_with_tenant_ids.push_back(extra_tenant_id)); OZ(stat_converter_info.col_schemas_.push_back(vt_col_schema)); OZ(stat_converter_info.real_column_ids_.push_back(real_col_schema->get_column_id())); if (0 == real_col_schema->get_column_name_str().case_compare(ObString("TENANT_ID"))) { stat_converter_info.tenant_id_col_id_ = vt_column_id; } break; } } if (OB_FAIL(ret)) { } else if (UINT64_MAX == real_column_id) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected status: column not found", K(ret), K(vt_column_id), K(k)); } } if (OB_SUCC(ret)) { stat_converter_info.use_real_tenant_id_ = vt_mapping->use_real_tenant_id_; } return ret; } int ObTableColStatSqlService::fetch_column_stat(const ObColumnStat::Key& key, ObColumnStat& stat) { int ret = OB_SUCCESS; DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_); SMART_VAR(ObMySQLProxy::MySQLResult, res) { sqlclient::ObMySQLResult* result = NULL; ObSqlString sql; ObStatConverterInfo stat_converter_info; const uint64_t tenant_id = extract_tenant_id(key.table_id_); const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id); if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (!key.is_valid()) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", K(key), K(ret)); } else if (OB_FAIL(init_vt_converter(tenant_id, key.table_id_, key.column_id_, stat_converter_info))) { COMMON_LOG(WARN, "fail to init virtual table converter.", K(key), K(ret)); } else if (OB_FAIL(sql.append(MY_FETCH_COL_STAT_SQL))) { COMMON_LOG(WARN, "fail to append SQL stmt string.", K(MY_FETCH_COL_STAT_SQL), K(ret)); } else if (!stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE ((TENANT_ID=%lu AND TABLE_ID=%ld) OR (TENANT_ID=%lu AND TABLE_ID=%ld))" " AND PARTITION_ID=%ld AND COLUMN_ID=%ld ORDER BY TENANT_ID", ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id), ObSchemaUtils::get_extract_schema_id(exec_tenant_id, key.table_id_), tenant_id, key.table_id_, key.partition_id_, key.column_id_))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret)); } else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE ((TENANT_ID=%lu AND TABLE_ID=%ld) OR (TENANT_ID=%lu AND TABLE_ID=%ld))" " AND PARTITION_ID=%ld AND COLUMN_ID=%ld ORDER BY TENANT_ID", ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id), ObSchemaUtils::get_extract_schema_id(exec_tenant_id, stat_converter_info.real_table_id_), tenant_id, stat_converter_info.real_table_id_, key.partition_id_, stat_converter_info.real_column_ids_.at(0)))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret)); } else if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) { COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret)); } else if (NULL == (result = res.get_result())) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret)); } else if (OB_FAIL(result->next())) { if (OB_ITER_END != ret) { COMMON_LOG(WARN, "result next failed, ", K(key), K(ret)); } else { ret = OB_ENTRY_NOT_EXIST; } } else if (OB_FAIL(fill_column_stat(key.table_id_, *result, stat, 0, stat_converter_info))) { COMMON_LOG(WARN, "read stat from result failed. ", K(key), K(ret)); } else { COMMON_LOG(INFO, "succeed to get column stat", K(stat)); } } return ret; } int ObTableColStatSqlService::fetch_table_stat( const common::ObPartitionKey& key, ObIArray>& all_part_stats) { int ret = OB_SUCCESS; DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_); SMART_VAR(ObMySQLProxy::MySQLResult, res) { sqlclient::ObMySQLResult* result = NULL; ObSqlString sql; const char* table_name = NULL; uint64_t exec_tenant_id = OB_SYS_TENANT_ID; all_part_stats.reset(); ObStatConverterInfo stat_converter_info; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (!key.is_valid()) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", K(key), K(ret)); } else { if (is_sys_table(key.get_table_id())) { table_name = oceanbase::share::OB_ALL_ROOT_TABLE_TNAME; exec_tenant_id = OB_SYS_TENANT_ID; } else { table_name = oceanbase::share::OB_ALL_TENANT_PARTITION_META_TABLE_TNAME; exec_tenant_id = extract_tenant_id(key.get_table_id()); } if (OB_FAIL(init_vt_converter(exec_tenant_id, key.table_id_, stat_converter_info))) { COMMON_LOG(WARN, "fail to init virtual table converter.", K(key), K(ret)); } else if (OB_FAIL( sql.append_fmt("SELECT partition_id, data_version,row_count,data_size FROM %s ", table_name))) { COMMON_LOG(WARN, "fail to append SQL stmt string.", K(sql), K(ret)); } else if (!stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE TENANT_ID = %ld AND TABLE_ID=%ld AND REPLICA_TYPE = 0 AND STATUS = " "'REPLICA_STATUS_NORMAL' ORDER BY data_version DESC", common::extract_tenant_id(key.get_table_id()), key.get_table_id()))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret)); } else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE TENANT_ID = %ld AND TABLE_ID=%ld AND REPLICA_TYPE = 0 AND STATUS = " "'REPLICA_STATUS_NORMAL' ORDER BY data_version DESC", exec_tenant_id, stat_converter_info.real_table_id_))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret)); } else if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) { COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret)); } else if (NULL == (result = res.get_result())) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret)); } while (OB_SUCC(ret)) { int64_t partition_id = OB_INVALID_ID; std::pair part_stat; if (OB_FAIL(result->next())) { if (OB_ITER_END != ret) { COMMON_LOG(WARN, "result next failed.", K(ret)); } else if (all_part_stats.empty()) { ret = OB_ENTRY_NOT_EXIST; } else { ret = OB_SUCCESS; break; } } else if (OB_FAIL(fill_table_stat(*result, partition_id, part_stat.second))) { COMMON_LOG(WARN, "read stat from result failed. ", K(ret)); } else if (OB_FAIL(part_stat.first.init(key.get_table_id(), partition_id, key.get_partition_cnt()))) { LOG_WARN("failed to init partition key", K(ret)); } else if (OB_FAIL(all_part_stats.push_back(part_stat))) { LOG_WARN("failed to push back partition stats", K(ret)); } } } } return ret; } int ObTableColStatSqlService::fetch_batch_stat(const uint64_t table_id, const ObIArray& partition_id, const ObIArray& column_id, ObIAllocator& allocator, common::ObIArray& stats, const bool use_pure_id) { int ret = OB_SUCCESS; DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_); SMART_VAR(ObMySQLProxy::MySQLResult, res) { sqlclient::ObMySQLResult* result = NULL; ObSqlString sql; stats.reuse(); ObStatConverterInfo stat_converter_info; const uint64_t tenant_id = extract_tenant_id(table_id); const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id); if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (OB_INVALID_ID == table_id) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid argument.", K(ret), K(table_id), K(partition_id)); } else if (OB_UNLIKELY(partition_id.empty() || column_id.empty())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("column stat entry size is invalid", K(ret), K(partition_id.count()), K(column_id.count())); } else if (OB_FAIL(init_vt_converter(tenant_id, table_id, column_id, stat_converter_info))) { COMMON_LOG(WARN, "fail to init virtual table converter.", K(ret)); } else if (OB_FAIL(sql.append(MY_FETCH_COL_STAT_SQL))) { COMMON_LOG(WARN, "fail to append SQL stmt string.", K(ret), K(MY_FETCH_COL_STAT_SQL)); } else if (!stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE TENANT_ID=%lu AND TABLE_ID = %ld AND PARTITION_ID IN ", use_pure_id ? ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id) : tenant_id, use_pure_id ? ObSchemaUtils::get_extract_schema_id(exec_tenant_id, table_id) : table_id))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(ret), K(MY_FETCH_COL_STAT_SQL)); } else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(sql.append_fmt(" WHERE TENANT_ID=%lu AND TABLE_ID = %ld AND PARTITION_ID IN ", use_pure_id ? ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id) : tenant_id, use_pure_id ? ObSchemaUtils::get_extract_schema_id(exec_tenant_id, stat_converter_info.real_table_id_) : stat_converter_info.real_table_id_))) { COMMON_LOG(WARN, "fail to append SQL where string.", K(ret), K(MY_FETCH_COL_STAT_SQL)); } for (int64_t i = 0; OB_SUCC(ret) && i < partition_id.count(); ++i) { if (OB_FAIL(sql.append_fmt( "%c%lu%c", (i == 0 ? '(' : ' '), partition_id.at(i), (i < partition_id.count() - 1 ? ',' : ')')))) { COMMON_LOG(WARN, "fail to append SQL in string. ", K(ret), K(i)); } } if (OB_SUCC(ret)) { if (OB_FAIL(sql.append_fmt(" AND COLUMN_ID IN "))) { COMMON_LOG(WARN, "fail to append column id filter.", K(ret), K(MY_FETCH_COL_STAT_SQL)); } } if (!stat_converter_info.is_vt_mapping_) { for (int64_t i = 0; OB_SUCC(ret) && i < column_id.count(); ++i) { if (OB_FAIL(sql.append_fmt( "%c%lu%c", (i == 0 ? '(' : ' '), column_id.at(i), (i < column_id.count() - 1 ? ',' : ')')))) { COMMON_LOG(WARN, "fail to append SQL in string", K(ret), K(i)); } } } else { for (int64_t i = 0; OB_SUCC(ret) && i < stat_converter_info.real_column_ids_.count(); ++i) { if (OB_FAIL(sql.append_fmt("%c%lu%c", (i == 0 ? '(' : ' '), stat_converter_info.real_column_ids_.at(i), (i < stat_converter_info.real_column_ids_.count() - 1 ? ',' : ')')))) { COMMON_LOG(WARN, "fail to append SQL in string", K(ret), K(i)); } } } if (OB_SUCC(ret)) { void* tmp_ptr = NULL; ObColumnStat* column_stat = NULL; if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) { COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret)); } else if (NULL == (result = res.get_result())) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret)); } else { int64_t idx = 0; while (OB_SUCC(ret)) { if (OB_FAIL(result->next())) { if (OB_ITER_END != ret) { COMMON_LOG(WARN, "result next failed.", K(ret)); } else if (stats.empty()) { ret = OB_ENTRY_NOT_EXIST; } else { ret = OB_SUCCESS; break; } } else if (OB_ISNULL(tmp_ptr = allocator.alloc(sizeof(ObColumnStat))) || OB_ISNULL(column_stat = new (tmp_ptr) ObColumnStat(allocator)) || OB_UNLIKELY(!column_stat->is_writable())) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "failed to allocate memory for ObColumnStat", K(ret), "size", sizeof(ObColumnStat)); } else if (OB_FAIL(fill_column_stat(table_id, *result, *column_stat, idx, stat_converter_info))) { COMMON_LOG(WARN, "read stat from result failed. ", K(ret), K(table_id), K(partition_id)); } else if (OB_FAIL(stats.push_back(column_stat))) { LOG_WARN("failed to push back column stat", K(ret)); } else { #if !defined(NDEBUG) COMMON_LOG(INFO, "succeed to get column stat", K(*column_stat)); #endif tmp_ptr = NULL; column_stat = NULL; ++idx; } } } } } return ret; } int ObTableColStatSqlService::insert_or_update_column_stats(const ObIArray& stats) { int ret = OB_SUCCESS; ObMySQLTransaction trans; ObSqlString sql; ObSqlString values; share::ObDMLSqlSplicer dml; ObArenaAllocator arean(ObModIds::OB_BUFFER); int64_t affected_rows = 0; uint64_t tenant_id = OB_INVALID_TENANT_ID; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < stats.count(); ++i) { dml.reuse(); if (NULL == stats.at(i)) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "item in stats must not NULL, ", K(ret), K(i)); } else if (OB_INVALID_TENANT_ID != tenant_id && tenant_id != extract_tenant_id(stats.at(i)->get_table_id())) { ret = OB_NOT_SUPPORTED; LOG_WARN("update column stats with multi tenant not supported", K(ret), K(tenant_id), KPC(stats.at(i))); } else if (OB_FAIL(fill_dml_splicer(*stats.at(i), dml))) { COMMON_LOG(WARN, "fill add ObColumnStat stat.", K(ret), K(i), K(*stats.at(i))); } else { tenant_id = extract_tenant_id(stats.at(i)->get_table_id()); if (0 == i) { if (OB_FAIL(dml.splice_column_names(values))) { COMMON_LOG(WARN, "fail to splice column names.", K(ret)); } else if (OB_FAIL(sql.assign_fmt("INSERT /*+ use_plan_cache(none) */ INTO %s (%s) VALUES", USER_TAB_COL_STATISTICS, values.ptr()))) { COMMON_LOG(WARN, "fail to assign sql string.", K(ret)); } } } if (OB_SUCC(ret)) { values.reset(); if (OB_FAIL(dml.splice_values(values))) { COMMON_LOG(WARN, "fail to splice values.", K(ret)); } else if (OB_FAIL(sql.append_fmt("%s(%s)", 0 == i ? " " : " , ", values.ptr()))) { COMMON_LOG(WARN, "fail to assign sql string.", K(ret)); } else { if ((stats.count() - 1) == i) { if (OB_FAIL(sql.append(" ON DUPLICATE KEY UPDATE "))) { COMMON_LOG(WARN, "fail to append sql string.", K(ret)); } else if (OB_FAIL(sql.append(" version = values(version)")) || OB_FAIL(sql.append(", last_rebuild_version = values(last_rebuild_version)")) || OB_FAIL(sql.append(", num_distinct = values(num_distinct)")) || OB_FAIL(sql.append(", num_null = values(num_null)")) || OB_FAIL(sql.append(", min_value = values(min_value)")) || OB_FAIL(sql.append(", max_value = values(max_value)")) || OB_FAIL(sql.append(", llc_bitmap = values(llc_bitmap)")) || OB_FAIL(sql.append(", llc_bitmap_size = values(llc_bitmap_size)"))) { COMMON_LOG(WARN, "fail to append sql string.", K(ret)); } } } } } } if (OB_SUCC(ret)) { const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id); if (OB_FAIL(trans.start(mysql_proxy_))) { COMMON_LOG(WARN, "fail to start transaction. ", K(ret)); } else if (OB_FAIL(mysql_proxy_->write(exec_tenant_id, sql.ptr(), affected_rows))) { COMMON_LOG(WARN, "fail to exec sql. ", K(ret), K(tenant_id)); } else if (affected_rows > 2 * stats.count()) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "unexpected affected rows.", K(ret), "expect_affect_rows", stats.count(), "actual_affect_rows", affected_rows); } } if (OB_SUCC(ret)) { if (OB_FAIL(trans.end(true))) { COMMON_LOG(WARN, "fail to commit transacrion.", K(ret)); } } else { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = trans.end(false))) { COMMON_LOG(WARN, "fail to rollback transaction. ", K(tmp_ret)); } } return ret; } // replace into statement is not supported for now, use dml splice (insert_or_update) as substitution. int ObTableColStatSqlService::insert_or_update_column_stat(const ObColumnStat& stat) { int ret = OB_SUCCESS; const uint64_t tenant_id = extract_tenant_id(stat.get_table_id()); const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id); ObMySQLTransaction trans; share::ObDMLSqlSplicer dml; share::ObDMLExecHelper dml_exec_helper(*mysql_proxy_, exec_tenant_id); // TODO min,max value could be very large?? ObArenaAllocator arena(ObModIds::OB_BUFFER); const int64_t total_buffer_size = stat.get_min_value().get_serialize_size() * 3 + stat.get_min_value().get_serialize_size() * 3 + stat.get_llc_bitmap_size() * 2 + 3; // (2 bytes for c string end \0); int64_t pos = 0; int64_t min_value_str_pos = 0; int64_t max_value_str_pos = 0; int64_t llc_str_pos = 0; int64_t affected_rows = 0; int64_t llc_comp_size = 0; char* all_field_buf = NULL; char* llc_comp_buf = NULL; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (!stat.is_valid()) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", K(stat), K(ret)); } else if (NULL == (all_field_buf = static_cast(arena.alloc(total_buffer_size)))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "cannot allocate memory.", K(total_buffer_size), K(ret)); } else if (OB_FAIL(serialize_to_hex_cstr( stat.get_min_value(), all_field_buf, total_buffer_size, pos, min_value_str_pos))) { COMMON_LOG(WARN, "serialize min obj value failed.", K(ret)); } else if (OB_FAIL(serialize_to_hex_cstr( stat.get_max_value(), all_field_buf, total_buffer_size, pos, max_value_str_pos))) { COMMON_LOG(WARN, "serialize max obj value failed.", K(ret)); } else if (OB_FAIL(get_compressed_llc_bitmap( arena, stat.get_llc_bitmap(), stat.get_llc_bitmap_size(), llc_comp_buf, llc_comp_size))) { COMMON_LOG(WARN, "get_compressed_llc_bitmap failed.", K(ret)); } else if (OB_FAIL(common::to_hex_cstr( llc_comp_buf, llc_comp_size, all_field_buf, total_buffer_size, pos, llc_str_pos))) { COMMON_LOG(WARN, "serialize llc bitmap failed.", K(llc_comp_size), K(ret)); } else { if (OB_FAIL(dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))) || OB_FAIL(dml.add_pk_column("table_id", ObSchemaUtils::get_extract_schema_id(tenant_id, stat.get_table_id()))) || OB_FAIL(dml.add_pk_column("partition_id", stat.get_partition_id())) || OB_FAIL(dml.add_pk_column("column_id", stat.get_column_id())) || OB_FAIL(dml.add_column("version", stat.get_version())) || OB_FAIL(dml.add_column("last_rebuild_version", stat.get_last_rebuild_version())) || OB_FAIL(dml.add_column("num_distinct", stat.get_num_distinct())) || OB_FAIL(dml.add_column("num_null", stat.get_num_null())) || OB_FAIL(dml.add_column("min_value", all_field_buf + min_value_str_pos)) || OB_FAIL(dml.add_column("max_value", all_field_buf + max_value_str_pos)) || OB_FAIL(dml.add_column("llc_bitmap", all_field_buf + llc_str_pos)) || OB_FAIL(dml.add_column("llc_bitmap_size", llc_comp_size * 2))) { COMMON_LOG(WARN, "add column failed", K(ret)); } else if (OB_FAIL(trans.start(mysql_proxy_))) { COMMON_LOG(WARN, "fail to to start transaction. ", K(ret)); } else if (OB_FAIL(dml_exec_helper.exec_insert_update(USER_TAB_COL_STATISTICS, dml, affected_rows))) { COMMON_LOG(WARN, "fail to to write transaction. ", K(ret)); } else if (affected_rows > 2) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "replace into return grate than 2", K(affected_rows), K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(trans.end(true))) { COMMON_LOG(WARN, "fail to commit transaction.", K(ret)); } } else { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = trans.end(false))) { COMMON_LOG(WARN, "fail to rollback transaction. ", K(tmp_ret)); } } return ret; } int ObTableColStatSqlService::fill_column_stat(const uint64_t table_id, common::sqlclient::ObMySQLResult& result, ObColumnStat& stat, int64_t idx, ObStatConverterInfo& stat_converter_info) { int ret = OB_SUCCESS; uint64_t dummy = 0; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } // after 2.2.4 __all_column_statistic stores pure table id (without tenant_id) // the stat cache stores full table id (with tenant_id) stat.set_table_id(table_id); EXTRACT_INT_FIELD_MYSQL(result, "tenant_id", dummy, uint64_t); EXTRACT_INT_FIELD_MYSQL(result, "table_id", dummy, uint64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, partition_id, stat, uint64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, column_id, stat, uint64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, version, stat, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, last_rebuild_version, stat, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, num_distinct, stat, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, num_null, stat, int64_t); ObArenaAllocator arena(ObModIds::OB_BUFFER); char* bitmap_buf = NULL; ObString str_field; EXTRACT_VARCHAR_FIELD_MYSQL(result, "llc_bitmap", str_field); if (OB_SUCC(ret)) { if (NULL == (bitmap_buf = static_cast(arena.alloc(str_field.length())))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "allocate memory for llc_bitmap failed.", K(str_field.length()), K(ret)); } else { common::str_to_hex(str_field.ptr(), str_field.length(), bitmap_buf, str_field.length()); } } if (OB_SUCC(ret)) { // decompress llc bitmap; char* decomp_buf = NULL; int64_t decomp_size = ObColumnStat::NUM_LLC_BUCKET; const int64_t bitmap_size = str_field.length() / 2; if (OB_FAIL(get_decompressed_llc_bitmap(arena, bitmap_buf, bitmap_size, decomp_buf, decomp_size))) { COMMON_LOG(WARN, "decompress bitmap buffer failed.", K(ret)); } else if (OB_FAIL(stat.store_llc_bitmap(decomp_buf, decomp_size))) { COMMON_LOG( WARN, "set llc bitmap failed.", KP(bitmap_buf), K(bitmap_size), KP(decomp_buf), K(decomp_size), K(ret)); } } common::ObObj obj; EXTRACT_VARCHAR_FIELD_MYSQL(result, "min_value", str_field); if (OB_SUCC(ret)) { if (stat_converter_info.is_vt_mapping_ && idx >= stat_converter_info.column_ids_.count()) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "unexpected status: column idx is invalid", K(ret), "column count", stat_converter_info.column_ids_.count(), "column idx", idx); } else if (OB_FAIL(deserialize_hex_cstr(str_field.ptr(), str_field.length(), arena, obj))) { COMMON_LOG(WARN, "deserialize_hex_cstr min value failed.", K(stat), K(ret)); } else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(stat_converter_info.vt_result_converter_.convert_column( obj, stat_converter_info.column_ids_.at(idx), idx))) { } else if (OB_FAIL(stat.store_min_value(obj))) { COMMON_LOG(WARN, "store min value failed.", K(stat), K(ret)); } } EXTRACT_VARCHAR_FIELD_MYSQL(result, "max_value", str_field); if (OB_SUCC(ret)) { if (stat_converter_info.is_vt_mapping_ && idx >= stat_converter_info.column_ids_.count()) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "unexpected status: column idx is invalid", K(ret), "column count", stat_converter_info.column_ids_.count(), "column idx", idx); } else if (OB_FAIL(deserialize_hex_cstr(str_field.ptr(), str_field.length(), arena, obj))) { COMMON_LOG(WARN, "deserialize_hex_cstr max value failed.", K(stat), K(ret)); } else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(stat_converter_info.vt_result_converter_.convert_column( obj, stat_converter_info.column_ids_.at(idx), idx))) { } else if (OB_FAIL(stat.store_max_value(obj))) { COMMON_LOG(WARN, "store max value failed.", K(stat), K(ret)); } } UNUSED(dummy); return ret; } int ObTableColStatSqlService::fill_table_stat( common::sqlclient::ObMySQLResult& result, int64_t& part_id, ObTableStat& stat) { int ret = OB_SUCCESS; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } EXTRACT_INT_FIELD_MYSQL(result, "partition_id", part_id, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, data_version, stat, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, row_count, stat, int64_t); EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, data_size, stat, int64_t); if (OB_SUCC(ret)) { if (stat.get_row_count() > 0) { stat.set_average_row_size(stat.get_data_size() / stat.get_row_count()); } } return ret; } int ObTableColStatSqlService::serialize_to_hex_cstr( const common::ObObj& obj, char* buf, int64_t buf_len, int64_t& pos, int64_t& cstr_pos) { int ret = OB_SUCCESS; int64_t hex_len = 0; int64_t start_pos = pos; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (NULL == buf || buf_len < 0 || pos < 0) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(pos), K(ret)); } else if (OB_FAIL(obj.serialize(buf, buf_len, pos))) { COMMON_LOG(WARN, "serialize obj failed.", KP(buf), K(buf_len), K(pos), K(ret)); } else { hex_len = pos - start_pos; if (OB_FAIL(common::to_hex_cstr(buf + start_pos, hex_len, buf, buf_len, pos, cstr_pos))) { COMMON_LOG(WARN, "Failed to transform to hex cstr", K(ret)); } } return ret; } int ObTableColStatSqlService::deserialize_hex_cstr(char* buf, int64_t buf_len, common::ObObj& obj) { int ret = OB_SUCCESS; int64_t pos = 0; int64_t ret_len = 0; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (NULL == buf || buf_len < 0) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(ret)); } else if (buf_len != (ret_len = common::str_to_hex(buf, static_cast(buf_len), buf, static_cast(buf_len)))) { // str_to_hex can use input as output, convert char in placement. ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "transfer str to hex failed.", K(buf), K(buf_len), K(ret_len), K(ret)); } else if (OB_FAIL(obj.deserialize(buf, ret_len / 2, pos))) { COMMON_LOG(WARN, "deserialize obj failed.", K(buf), K(buf_len), K(pos), K(ret)); } return ret; } int ObTableColStatSqlService::deserialize_hex_cstr( char* buf, int64_t buf_len, ObIAllocator& allocator, common::ObObj& obj) { int ret = OB_SUCCESS; int64_t pos = 0; int64_t ret_len = 0; char* resbuf = NULL; if (!inited_) { ret = OB_NOT_INIT; COMMON_LOG(WARN, "sql service has not initialized.", K(ret)); } else if (NULL == buf || buf_len < 0) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(ret)); } else if (NULL == (resbuf = static_cast(allocator.alloc(buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "cannot allocate memory for deserialize obj.", K(buf_len), K(ret)); } else if (buf_len != (ret_len = common::str_to_hex( buf, static_cast(buf_len), resbuf, static_cast(buf_len)))) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "transfer str to hex failed.", K(buf), K(buf_len), K(ret_len), K(ret)); } else if (OB_FAIL(obj.deserialize(resbuf, ret_len, pos))) { COMMON_LOG(WARN, "deserialize obj failed.", K(buf), K(buf_len), K(pos), K(ret)); } return ret; } int ObTableColStatSqlService::get_compressed_llc_bitmap( ObIAllocator& allocator, const char* bitmap_buf, int64_t bitmap_size, char*& comp_buf, int64_t& comp_size) { int ret = OB_SUCCESS; ObCompressor* compressor = NULL; int64_t max_comp_size = 0; if (NULL == bitmap_buf || bitmap_size <= 0) { ret = common::OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid arguments.", KP(bitmap_buf), K(bitmap_size), K(ret)); } else if (OB_FAIL(ObCompressorPool::get_instance().get_compressor(bitmap_compress_lib_name, compressor))) { COMMON_LOG(WARN, "cannot create compressor, do not compress data.", K(bitmap_compress_lib_name), K(ret)); } else if (NULL == compressor) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "compressor is NULL, do not compress data.", K(bitmap_compress_lib_name), K(ret)); } else if (OB_FAIL(compressor->get_max_overflow_size(bitmap_size, max_comp_size))) { COMMON_LOG(WARN, "get max overflow size failed.", K(bitmap_compress_lib_name), K(bitmap_size), K(ret)); } else { max_comp_size += bitmap_size; if (NULL == (comp_buf = static_cast(allocator.alloc(max_comp_size)))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "cannot allocate compressed buffer.", K(max_comp_size), K(ret)); } else if (OB_FAIL(compressor->compress(bitmap_buf, bitmap_size, comp_buf, max_comp_size, comp_size))) { COMMON_LOG(WARN, "compress llc bitmap failed.", K(ret)); } else if (comp_size >= bitmap_size) { // compress is not work, just use original data. comp_buf = const_cast(bitmap_buf); comp_size = bitmap_size; } } return ret; } int ObTableColStatSqlService::get_decompressed_llc_bitmap( ObIAllocator& allocator, const char* comp_buf, int64_t comp_size, char*& bitmap_buf, int64_t& bitmap_size) { int ret = OB_SUCCESS; const int64_t max_bitmap_size = ObColumnStat::NUM_LLC_BUCKET; // max size of uncompressed buffer. ObCompressor* compressor = NULL; if (comp_size >= ObColumnStat::NUM_LLC_BUCKET) { // not compressed bitmap, use directly; bitmap_buf = const_cast(comp_buf); bitmap_size = comp_size; } else if (NULL == (bitmap_buf = static_cast(allocator.alloc(max_bitmap_size)))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "allocate memory for uncompressed data failed.", K(max_bitmap_size), K(ret)); } else if (OB_FAIL(ObCompressorPool::get_instance().get_compressor(bitmap_compress_lib_name, compressor))) { COMMON_LOG(WARN, "cannot create compressor, do not uncompress data.", K(bitmap_compress_lib_name), K(ret)); } else if (NULL == compressor) { ret = OB_ERR_UNEXPECTED; COMMON_LOG(WARN, "compressor is NULL, do not compress data.", K(bitmap_compress_lib_name), K(ret)); } else if (OB_FAIL(compressor->decompress(comp_buf, comp_size, bitmap_buf, max_bitmap_size, bitmap_size))) { COMMON_LOG(WARN, "decompress bitmap buffer failed.", KP(comp_buf), K(comp_size), KP(bitmap_buf), K(max_bitmap_size), K(bitmap_size), K(ret)); } return ret; } int ObTableColStatSqlService::fill_dml_splicer(const ObColumnStat& stat, share::ObDMLSqlSplicer& dml_splicer) { int ret = OB_SUCCESS; ObArenaAllocator arena(ObModIds::OB_BUFFER); const int64_t total_buffer_size = stat.get_min_value().get_serialize_size() * 3 + stat.get_min_value().get_serialize_size() * 3 + stat.get_llc_bitmap_size() * 2 + 3; int64_t pos = 0; int64_t min_value_str_pos = 0; int64_t max_value_str_pos = 0; int64_t llc_str_pos = 0; int64_t llc_comp_size = 0; char* all_field_buf = NULL; char* llc_comp_buf = NULL; if (!stat.is_valid()) { ret = OB_INVALID_ARGUMENT; COMMON_LOG(WARN, "invalid argument, ", K(ret), K(stat)); } else if (NULL == (all_field_buf = static_cast(arena.alloc(total_buffer_size)))) { ret = OB_ALLOCATE_MEMORY_FAILED; COMMON_LOG(ERROR, "cannot allocate memory.", K(ret), K(total_buffer_size)); } else if (OB_FAIL(serialize_to_hex_cstr( stat.get_min_value(), all_field_buf, total_buffer_size, pos, min_value_str_pos))) { COMMON_LOG(WARN, "serialize min obj value failed.", K(ret)); } else if (OB_FAIL(serialize_to_hex_cstr( stat.get_max_value(), all_field_buf, total_buffer_size, pos, max_value_str_pos))) { COMMON_LOG(WARN, "serialize max obj value failed.", K(ret)); } else if (OB_FAIL(get_compressed_llc_bitmap( arena, stat.get_llc_bitmap(), stat.get_llc_bitmap_size(), llc_comp_buf, llc_comp_size))) { COMMON_LOG(WARN, "get_compressed_llc_bitmap failed.", K(ret)); } else if (OB_FAIL(common::to_hex_cstr( llc_comp_buf, llc_comp_size, all_field_buf, total_buffer_size, pos, llc_str_pos))) { COMMON_LOG(WARN, "serialize llc bitmap failed.", K(ret), K(llc_comp_size)); } else { const uint64_t tenant_id = extract_tenant_id(stat.get_table_id()); if (OB_FAIL(dml_splicer.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))) || OB_FAIL(dml_splicer.add_pk_column( "table_id", ObSchemaUtils::get_extract_schema_id(tenant_id, stat.get_table_id()))) || OB_FAIL(dml_splicer.add_pk_column("partition_id", stat.get_partition_id())) || OB_FAIL(dml_splicer.add_pk_column("column_id", stat.get_column_id())) || OB_FAIL(dml_splicer.add_column("version", stat.get_version())) || OB_FAIL(dml_splicer.add_column("last_rebuild_version", stat.get_last_rebuild_version())) || OB_FAIL(dml_splicer.add_column("num_distinct", stat.get_num_distinct())) || OB_FAIL(dml_splicer.add_column("num_null", stat.get_num_null())) || OB_FAIL(dml_splicer.add_column("min_value", all_field_buf + min_value_str_pos)) || OB_FAIL(dml_splicer.add_column("max_value", all_field_buf + max_value_str_pos)) || OB_FAIL(dml_splicer.add_column("llc_bitmap", all_field_buf + llc_str_pos)) || OB_FAIL(dml_splicer.add_column("llc_bitmap_size", llc_comp_size * 2))) { COMMON_LOG(WARN, "add column failed.", K(ret)); } } return ret; } } // end of namespace common } // end of namespace oceanbase