From 73e340174910629ee8caaae0c661e5726adf6c9d Mon Sep 17 00:00:00 2001 From: bf0 Date: Fri, 24 Sep 2021 11:10:39 +0800 Subject: [PATCH] fix single partition opt bug --- src/share/part/ob_part_mgr_ad.cpp | 29 +++++++++------ src/share/part/ob_part_mgr_ad.h | 14 ++++---- .../engine/dml/ob_multi_part_insert_op.cpp | 2 +- src/sql/ob_sql_utils.cpp | 13 +++++++ src/sql/ob_sql_utils.h | 1 + src/sql/optimizer/ob_log_insert.cpp | 16 ++++++--- src/sql/optimizer/ob_log_update.cpp | 2 +- src/sql/optimizer/ob_table_location.cpp | 35 +++++++++++-------- src/sql/optimizer/ob_table_location.h | 15 ++++++-- 9 files changed, 87 insertions(+), 40 deletions(-) diff --git a/src/share/part/ob_part_mgr_ad.cpp b/src/share/part/ob_part_mgr_ad.cpp index a2a6591c86..336eade6a4 100644 --- a/src/share/part/ob_part_mgr_ad.cpp +++ b/src/share/part/ob_part_mgr_ad.cpp @@ -21,9 +21,9 @@ using namespace common; using namespace share::schema; namespace sql { // for hash/key/range_func part or insert statement -int ObPartMgrAD::get_part(ObPartMgr* part_mgr, const int64_t table_id, const ObPartitionLevel part_level, - const ObPartitionFuncType part_type, const bool insert_or_replace, const int64_t p_id, const ObObj& value, - ObIArray& partition_ids, int64_t* part_idx) +int ObPartMgrAD::get_part(ObPartMgr *part_mgr, const int64_t table_id, const ObPartitionLevel part_level, + const ObPartitionFuncType part_type, const bool report_err_if_partition_not_exist, const int64_t p_id, + const ObObj &value, ObIArray &partition_ids, int64_t *part_idx) { int ret = common::OB_SUCCESS; ObRowkey rowkey(const_cast(&value), 1); @@ -31,8 +31,15 @@ int ObPartMgrAD::get_part(ObPartMgr* part_mgr, const int64_t table_id, const ObP ObSEArray part_ids; if (OB_FAIL(range.build_range(table_id, rowkey))) { LOG_WARN("Failed to build range", K(ret)); - } else if (OB_FAIL(get_part( - part_mgr, table_id, part_level, part_type, insert_or_replace, p_id, range, partition_ids, part_idx))) { + } else if (OB_FAIL(get_part(part_mgr, + table_id, + part_level, + part_type, + report_err_if_partition_not_exist, + p_id, + range, + partition_ids, + part_idx))) { LOG_WARN("Failed to get part", K(ret)); } else { } // do nothing @@ -42,8 +49,8 @@ int ObPartMgrAD::get_part(ObPartMgr* part_mgr, const int64_t table_id, const ObP int ObPartMgrAD::get_part(common::ObPartMgr* part_mgr, const int64_t table_id, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_type, - const bool insert_or_replace, const int64_t p_id, const common::ObNewRow& row, - common::ObIArray& partition_ids, int64_t* part_idx) + const bool report_err_if_partition_not_exist, const int64_t p_id, const common::ObNewRow &row, + common::ObIArray &partition_ids, int64_t *part_idx) { int ret = OB_SUCCESS; ObSEArray part_ids; @@ -53,7 +60,7 @@ int ObPartMgrAD::get_part(common::ObPartMgr* part_mgr, const int64_t table_id, } else if (OB_FAIL(part_mgr->get_part(table_id, part_level, p_id, row, part_ids))) { LOG_WARN("Failed to get part from part_mgr", K(ret)); } else if (0 == part_ids.count()) { - if (insert_or_replace) { // For Insert or replace stmt, if no partition, report error + if (report_err_if_partition_not_exist) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE); } else if (share::schema::is_hash_like_part(part_type)) { // For other stmt @@ -126,8 +133,8 @@ int ObPartMgrAD::get_all_part(ObPartMgr* part_mgr, const int64_t table_id, const int ObPartMgrAD::get_part(common::ObPartMgr* part_mgr, const int64_t table_id, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_type, - const bool insert_or_replace, const int64_t p_id, const common::ObNewRange& range, - common::ObIArray& partition_ids, int64_t* part_idx) + const bool report_err_if_partition_not_exist, const int64_t p_id, const common::ObNewRange &range, + common::ObIArray &partition_ids, int64_t *part_idx) { int ret = OB_SUCCESS; ObSEArray part_ids; @@ -137,7 +144,7 @@ int ObPartMgrAD::get_part(common::ObPartMgr* part_mgr, const int64_t table_id, } else if (OB_FAIL(part_mgr->get_part(table_id, part_level, p_id, range, false, part_ids))) { LOG_WARN("Failed to get part from part_mgr", K(ret)); } else if (0 == part_ids.count()) { - if (insert_or_replace) { // For Insert or replace stmt, if no partition, report error + if (report_err_if_partition_not_exist) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE); } else if (PARTITION_FUNC_TYPE_RANGE != part_type && PARTITION_FUNC_TYPE_RANGE_COLUMNS != part_type && diff --git a/src/share/part/ob_part_mgr_ad.h b/src/share/part/ob_part_mgr_ad.h index 55b9c00afd..e2a8e7f3d5 100644 --- a/src/share/part/ob_part_mgr_ad.h +++ b/src/share/part/ob_part_mgr_ad.h @@ -34,15 +34,15 @@ public: // for hash/key/range_func part or insert statement static int get_part(common::ObPartMgr* part_mgr, const int64_t table_id, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_type, - const bool insert_or_replace, const int64_t p_id, - const common::ObObj& value, // part func result - common::ObIArray& partition_ids, int64_t* part_idx); + const bool report_err_if_partition_not_exist, const int64_t p_id, + const common::ObObj &value, // part func result + common::ObIArray &partition_ids, int64_t *part_idx); // For range columns static int get_part(common::ObPartMgr* part_mgr, const int64_t table_id, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_type, - const bool insert_or_replace, const int64_t p_id, const common::ObNewRow& row, - common::ObIArray& partition_ids, int64_t* part_idx = NULL); + const bool report_err_if_partition_not_exist, const int64_t p_id, const common::ObNewRow &row, + common::ObIArray &partition_ids, int64_t *part_idx = NULL); /////////The for range range partition must only contain column. If there are multiple columns, range represents the /// column vector in the schema////// @@ -58,8 +58,8 @@ private: // Get point values range partition id static int get_part(common::ObPartMgr* part_mgr, const int64_t table_id, const share::schema::ObPartitionLevel part_level, const share::schema::ObPartitionFuncType part_type, - const bool insert_or_replace, const int64_t p_id, const common::ObNewRange& value, - common::ObIArray& partition_ids, int64_t* part_idx = NULL); + const bool report_err_if_partition_not_exist, const int64_t p_id, const common::ObNewRange &value, + common::ObIArray &partition_ids, int64_t *part_idx = NULL); }; } // namespace sql diff --git a/src/sql/engine/dml/ob_multi_part_insert_op.cpp b/src/sql/engine/dml/ob_multi_part_insert_op.cpp index b0fa673ee2..0c620bd441 100644 --- a/src/sql/engine/dml/ob_multi_part_insert_op.cpp +++ b/src/sql/engine/dml/ob_multi_part_insert_op.cpp @@ -127,7 +127,7 @@ int ObMultiPartInsertOp::shuffle_insert_row(bool& got_row) } else if (OB_FAIL(calc_part_id_expr->eval(eval_ctx_, partition_id_datum))) { LOG_WARN("fail to calc part id", K(ret), K(calc_part_id_expr)); } else if (ObExprCalcPartitionId::NONE_PARTITION_ID == partition_id_datum->get_int()) { - ret = OB_INVALID_ARGUMENT; + ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_WARN("no partition matched", K(ret), K(child_->get_spec().output_)); } else { if (OB_FAIL(add_var_to_array_no_dup(part_ids, partition_id_datum->get_int(), &part_idx))) { diff --git a/src/sql/ob_sql_utils.cpp b/src/sql/ob_sql_utils.cpp index d52863b327..40586bb2df 100644 --- a/src/sql/ob_sql_utils.cpp +++ b/src/sql/ob_sql_utils.cpp @@ -3890,3 +3890,16 @@ int ObSQLUtils::handle_audit_record( session.reset_audit_record(); return ret; } + +bool ObSQLUtils::is_one_part_table_can_skip_part_calc(const ObTableSchema &schema) +{ + bool can_skip = false; + if (!schema.is_partitioned_table()) { + can_skip = true; + } else if (schema.get_all_part_num() == 1 && schema.is_hash_part()) { + can_skip = true; + } else { + can_skip = false; + } + return can_skip; +} diff --git a/src/sql/ob_sql_utils.h b/src/sql/ob_sql_utils.h index 2da8968a74..dd8762f315 100644 --- a/src/sql/ob_sql_utils.h +++ b/src/sql/ob_sql_utils.h @@ -332,6 +332,7 @@ public: static int print_identifier(char* buf, const int64_t buf_len, int64_t& pos, common::ObCollationType connection_collation, const common::ObString& identifier_name); + static bool is_one_part_table_can_skip_part_calc(const share::schema::ObTableSchema &schema); private: static int check_ident_name(const common::ObCollationType cs_type, common::ObString& name, diff --git a/src/sql/optimizer/ob_log_insert.cpp b/src/sql/optimizer/ob_log_insert.cpp index 839788a716..9f1d8afe42 100644 --- a/src/sql/optimizer/ob_log_insert.cpp +++ b/src/sql/optimizer/ob_log_insert.cpp @@ -690,6 +690,7 @@ int ObLogInsert::need_multi_table_dml(AllocExchContext& ctx, ObShardingInfo& sha bool has_rand_part_key = false; bool has_subquery_part_key = false; bool trigger_exist = false; + bool is_one_part_table = false; bool is_match = false; ObInsertStmt* insert_stmt = static_cast(get_stmt()); is_needed = false; @@ -702,9 +703,12 @@ int ObLogInsert::need_multi_table_dml(AllocExchContext& ctx, ObShardingInfo& sha } else if (OB_ISNULL(tbl_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema is null", K(ret), K(insert_stmt)); + } else if (FALSE_IT(is_one_part_table = ObSQLUtils::is_one_part_table_can_skip_part_calc(*tbl_schema))) { + } else if (insert_stmt->is_ignore() && !is_one_part_table) { + is_needed = true; } else if (modify_multi_tables()) { is_needed = true; - } else if (is_table_update_part_key() && tbl_schema->get_all_part_num() > 1) { + } else if (is_table_update_part_key() && !is_one_part_table) { is_needed = true; } @@ -731,12 +735,16 @@ int ObLogInsert::need_multi_table_dml(AllocExchContext& ctx, ObShardingInfo& sha } else if (get_part_hint() != NULL && insert_stmt->value_from_select()) { is_needed = true; } else if (target_sharding_info.is_local()) { - is_needed = false; - sharding_info.copy_with_part_keys(target_sharding_info); + if (is_one_part_table || !table_partition_info_.get_table_location().is_all_partition()) { + is_needed = false; + sharding_info.copy_with_part_keys(target_sharding_info); + } else { + is_needed = true; + } } else if (OB_FAIL(input_sharding.push_back(&target_sharding_info)) || OB_FAIL(input_sharding.push_back(&child->get_sharding_info()))) { LOG_WARN("failed to push back sharding info", K(ret)); - } else if (ObLogicalOperator::compute_basic_sharding_info(input_sharding, output_sharding, is_basic)) { + } else if (OB_FAIL(ObLogicalOperator::compute_basic_sharding_info(input_sharding, output_sharding, is_basic))) { LOG_WARN("failed to compute basic sharding info", K(ret)); } else if (is_basic) { is_needed = false; diff --git a/src/sql/optimizer/ob_log_update.cpp b/src/sql/optimizer/ob_log_update.cpp index 45670f9458..578672844f 100644 --- a/src/sql/optimizer/ob_log_update.cpp +++ b/src/sql/optimizer/ob_log_update.cpp @@ -269,7 +269,7 @@ int ObLogUpdate::need_multi_table_dml(AllocExchContext& ctx, ObShardingInfo& sha LOG_WARN("schema guard is null"); } else if (OB_FAIL(schema_guard->get_table_schema(ref_table_id, tbl_schema))) { LOG_WARN("get table schema failed", K(ret)); - } else if (is_update_part_key && tbl_schema->get_all_part_num() > 1) { + } else if (is_update_part_key && !ObSQLUtils::is_one_part_table_can_skip_part_calc(*tbl_schema)) { is_needed = true; sharding_info.reset(); } diff --git a/src/sql/optimizer/ob_table_location.cpp b/src/sql/optimizer/ob_table_location.cpp index 6d0cf55fbe..266536ab2f 100644 --- a/src/sql/optimizer/ob_table_location.cpp +++ b/src/sql/optimizer/ob_table_location.cpp @@ -960,6 +960,7 @@ ObTableLocation& ObTableLocation::operator=(const ObTableLocation& other) use_calc_part_by_rowid_ = other.use_calc_part_by_rowid_; is_valid_range_columns_part_range_ = other.is_valid_range_columns_part_range_; is_valid_range_columns_subpart_range_ = other.is_valid_range_columns_subpart_range_; + report_err_for_pruned_partition_not_exist_ = other.report_err_for_pruned_partition_not_exist_; for (int64_t i = 0; OB_SUCC(ret) && i < other.list_part_array_.count(); i++) { ObListPartMapValue value; value.part_id_ = other.list_part_array_.at(i).part_id_; @@ -1214,6 +1215,7 @@ int ObTableLocation::init_table_location(ObSqlSchemaGuard& schema_guard, uint64_ is_contain_mv_ = stmt.get_query_ctx()->is_contain_mv_; if (stmt.is_insert_stmt()) { set_simple_insert_or_replace(); + report_err_for_pruned_partition_not_exist_ = true; } } if (OB_FAIL(ret)) { @@ -1396,6 +1398,9 @@ int ObTableLocation::init(const ObTableSchema* table_schema, ObDMLStmt& stmt, Ob is_contain_mv_ = stmt.get_query_ctx()->is_contain_mv_; is_partitioned_ = true; // direction_ = direction; + if (stmt.is_insert_stmt()) { + report_err_for_pruned_partition_not_exist_ = true; + } if (OB_UNLIKELY(inited_)) { ret = OB_INIT_TWICE; @@ -4055,13 +4060,12 @@ int ObTableLocation::calc_partition_id_by_func_value(ObExprCtx& expr_ctx, common } else { } } else { - bool insert_or_replace = is_simple_insert_or_replace(); if (NULL == part_ids) { if (OB_FAIL(ObPartMgrAD::get_part(part_mgr, ref_table_id_, PARTITION_LEVEL_ONE, part_type_, - insert_or_replace, + report_err_for_pruned_partition_not_exist_, -1, result, partition_ids, @@ -4074,7 +4078,7 @@ int ObTableLocation::calc_partition_id_by_func_value(ObExprCtx& expr_ctx, common ref_table_id_, PARTITION_LEVEL_TWO, subpart_type_, - insert_or_replace, + report_err_for_pruned_partition_not_exist_, part_ids->at(idx), result, partition_ids, @@ -4138,6 +4142,7 @@ int ObTableLocation::calc_partition_ids_by_rowkey(ObExecContext& exec_ctx, ObPar int ObTableLocation::get_list_part( const ObNewRow& row, bool insert_or_replace, common::ObIArray& partition_ids, int64_t* part_idx) const { + UNUSED(insert_or_replace); int ret = OB_SUCCESS; ObListPartMapValue* value = NULL; ObListPartMapKey key; @@ -4146,7 +4151,7 @@ int ObTableLocation::get_list_part( if (ret == OB_HASH_NOT_EXIST) { LOG_TRACE("get list part not exist", K(key)); if (list_default_part_id_ == OB_INVALID_ID) { - if (insert_or_replace) { + if (report_err_for_pruned_partition_not_exist_) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; } else { ret = OB_SUCCESS; @@ -4213,6 +4218,7 @@ int ObTableLocation::get_hash_part( int ObTableLocation::get_range_part( const ObNewRow& row, bool insert_or_replace, common::ObIArray& partition_ids, int64_t* part_idx) const { + UNUSED(insert_or_replace); int ret = OB_SUCCESS; int64_t high = partition_num_ - 1; int64_t low = 0; @@ -4224,7 +4230,7 @@ int ObTableLocation::get_range_part( LOG_WARN("get range part with optimization should have 1 column", K(ret), K(row.get_count())); } else if (cur_obj.is_null()) { // For Insert or replace stmt, if no partition, report error - if (!range_obj_arr_[high].is_max_value() && insert_or_replace) { + if (!range_obj_arr_[high].is_max_value() && report_err_for_pruned_partition_not_exist_) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE); } @@ -4243,7 +4249,7 @@ int ObTableLocation::get_range_part( if (!range_obj_arr_[res].is_max_value() && !ObObjCmpFuncs::compare_oper_nullsafe( range_obj_arr_[res], cur_obj, range_obj_arr_[mid].get_collation_type(), CO_GT)) { - if (insert_or_replace) { // For Insert or replace stmt, if no partition, report error + if (report_err_for_pruned_partition_not_exist_) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE); } @@ -4312,11 +4318,11 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O part_projector_.project_part_row(PARTITION_LEVEL_ONE, row); if (related_part_expr_idx_ == OB_INVALID_INDEX) { if (use_list_part_map_) { - if (OB_FAIL(get_list_part(row, insert_or_replace, partition_ids, &part_idx))) { + if (OB_FAIL(get_list_part(row, report_err_for_pruned_partition_not_exist_, partition_ids, &part_idx))) { LOG_WARN("fail to get list part", K(row), K(ret)); } } else if (use_range_part_opt_) { - if (OB_FAIL(get_range_part(row, insert_or_replace, partition_ids, &part_idx))) { + if (OB_FAIL(get_range_part(row, report_err_for_pruned_partition_not_exist_, partition_ids, &part_idx))) { LOG_WARN("fail to get range part", K(row), K(ret)); } } else { @@ -4324,7 +4330,7 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O ref_table_id_, PARTITION_LEVEL_ONE, part_type_, - insert_or_replace, + report_err_for_pruned_partition_not_exist_, -1, row, partition_ids, @@ -4343,11 +4349,12 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O LOG_WARN("Failed to calc hash expr", K(ret), K(row), K(ref_table_id_)); } else { if (use_list_part_map_) { - if (OB_FAIL(get_list_part(func_result, insert_or_replace, partition_ids, &part_idx))) { + if (OB_FAIL(get_list_part( + func_result, report_err_for_pruned_partition_not_exist_, partition_ids, &part_idx))) { LOG_WARN("fail to get list part", K(ret)); } } else if (use_range_part_opt_) { - if (OB_FAIL(get_range_part(row, insert_or_replace, partition_ids, &part_idx))) { + if (OB_FAIL(get_range_part(row, report_err_for_pruned_partition_not_exist_, partition_ids, &part_idx))) { LOG_WARN("fail to get range part", K(ret)); } } else { @@ -4355,7 +4362,7 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O ref_table_id_, PARTITION_LEVEL_ONE, part_type_, - insert_or_replace, + report_err_for_pruned_partition_not_exist_, -1, func_result, partition_ids, @@ -4384,7 +4391,7 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O ref_table_id_, PARTITION_LEVEL_TWO, subpart_type_, - insert_or_replace, + report_err_for_pruned_partition_not_exist_, part_ids->at(idx), row, partition_ids, @@ -4406,7 +4413,7 @@ int ObTableLocation::calc_partition_id_by_row(ObExecContext& exec_ctx, common::O if (OB_FAIL(ret) || range_columns) { } else { if (use_hash_part_opt_) { - if (OB_FAIL(get_hash_part(func_result, insert_or_replace, partition_ids, &part_idx))) { + if (OB_FAIL(get_hash_part(func_result, report_err_for_pruned_partition_not_exist_, partition_ids, &part_idx))) { LOG_WARN("fail to get hash part", K(ret)); } } else if (OB_FAIL(calc_partition_id_by_func_value( diff --git a/src/sql/optimizer/ob_table_location.h b/src/sql/optimizer/ob_table_location.h index 268b24403e..fbef60e317 100644 --- a/src/sql/optimizer/ob_table_location.h +++ b/src/sql/optimizer/ob_table_location.h @@ -482,7 +482,8 @@ public: range_part_id_arr_(NULL), use_calc_part_by_rowid_(false), is_valid_range_columns_part_range_(false), - is_valid_range_columns_subpart_range_(false) + is_valid_range_columns_subpart_range_(false), + report_err_for_pruned_partition_not_exist_(false) {} // Used in situations where the optimizer does not adjust the destructor, to ensure that @@ -555,7 +556,8 @@ public: hash_part_array_(common::OB_MALLOC_NORMAL_BLOCK_SIZE, common::ModulePageAllocator(allocator_)), use_calc_part_by_rowid_(false), is_valid_range_columns_part_range_(false), - is_valid_range_columns_subpart_range_(false) + is_valid_range_columns_subpart_range_(false), + report_err_for_pruned_partition_not_exist_(false) {} virtual ~ObTableLocation() { @@ -839,6 +841,13 @@ public: int calculate_partition_ids_with_rowid(ObExecContext& exec_ctx, share::schema::ObSchemaGetterGuard& schema_guard, const ParamStore& params, common::ObIArray& part_ids) const; + inline bool is_all_partition() const + { + return (part_level_ == share::schema::PARTITION_LEVEL_ZERO) || + (part_get_all_ && (part_level_ == share::schema::PARTITION_LEVEL_ONE)) || + (part_get_all_ && subpart_get_all_ && (part_level_ == share::schema::PARTITION_LEVEL_TWO)); + } + TO_STRING_KV(K_(table_id), K_(ref_table_id), K_(part_num), K_(is_global_index), K_(duplicate_type), K_(part_expr_param_idxs), K_(part_projector), K_(part_expr), K_(gen_col_expr)); @@ -1134,6 +1143,8 @@ private: bool use_calc_part_by_rowid_; bool is_valid_range_columns_part_range_; bool is_valid_range_columns_subpart_range_; + + bool report_err_for_pruned_partition_not_exist_; }; } // namespace sql -- GitLab