fix pdml allocate partition id expr bug

This commit is contained in:
chimyue
2023-11-14 13:10:46 +00:00
committed by ob-robot
parent 0ad4149411
commit 4b1c5f93c0
2 changed files with 63 additions and 68 deletions

View File

@ -484,7 +484,8 @@ int ObLogDelUpd::generate_pdml_partition_id_expr()
// 2. 如果当前pdml op对应的表是分区表,就分配partition id expr // 2. 如果当前pdml op对应的表是分区表,就分配partition id expr
uint64_t table_id = OB_INVALID_ID; uint64_t table_id = OB_INVALID_ID;
ObOpPseudoColumnRawExpr *partition_id_expr = nullptr; ObOpPseudoColumnRawExpr *partition_id_expr = nullptr;
ObLogicalOperator *producer = NULL; ObLogExchange *producer = NULL;
ObLogTableScan *src_tsc = NULL;
if (OB_UNLIKELY(!is_pdml()) || if (OB_UNLIKELY(!is_pdml()) ||
OB_UNLIKELY(index_dml_infos_.count() != 1) || OB_UNLIKELY(index_dml_infos_.count() != 1) ||
OB_ISNULL(index_dml_infos_.at(0))) { OB_ISNULL(index_dml_infos_.at(0))) {
@ -492,87 +493,80 @@ int ObLogDelUpd::generate_pdml_partition_id_expr()
LOG_WARN("index info array is empty", K(ret)); LOG_WARN("index info array is empty", K(ret));
} else if (OB_FAIL(ObLogicalOperator::generate_pseudo_partition_id_expr(partition_id_expr))) { } else if (OB_FAIL(ObLogicalOperator::generate_pseudo_partition_id_expr(partition_id_expr))) {
LOG_WARN("fail allocate part id expr", K(table_id), K(ret)); LOG_WARN("fail allocate part id expr", K(table_id), K(ret));
} else if (OB_FAIL(find_pdml_part_id_producer(*this, } else if (OB_FAIL(find_pdml_part_id_producer(get_child(ObLogicalOperator::first_child),
index_dml_infos_.at(0)->loc_table_id_, index_dml_infos_.at(0)->loc_table_id_,
index_dml_infos_.at(0)->ref_table_id_, index_dml_infos_.at(0)->ref_table_id_,
producer))) { producer,
src_tsc))) {
LOG_WARN("find pdml partition id expr producer failed", K(ret)); LOG_WARN("find pdml partition id expr producer failed", K(ret));
} else if (NULL == producer) { } else if (NULL != src_tsc && NULL != producer) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("can not found pdml partition id expr producer", K(ret));
} else {
pdml_partition_id_expr_ = partition_id_expr; pdml_partition_id_expr_ = partition_id_expr;
if (producer->get_type() == log_op_def::LOG_EXCHANGE) { producer->set_partition_id_expr(partition_id_expr);
static_cast<ObLogExchange *>(producer)->set_partition_id_expr(partition_id_expr); } else if (NULL != src_tsc) {
} else if (producer->get_type() == log_op_def::LOG_TABLE_SCAN) { pdml_partition_id_expr_ = partition_id_expr;
static_cast<ObLogTableScan *>(producer)->set_tablet_id_expr(partition_id_expr); src_tsc->set_tablet_id_expr(partition_id_expr);
} else { } else if (NULL != producer) {
ret = OB_ERR_UNEXPECTED; pdml_partition_id_expr_ = partition_id_expr;
LOG_WARN("unexpected type of pdml partition id producer", K(ret), K(producer)); producer->set_partition_id_expr(partition_id_expr);
} } else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("can not found pdml partition id expr producer", K(ret), K(producer), K(src_tsc));
} }
return ret; return ret;
} }
int ObLogDelUpd::find_pdml_part_id_producer(ObLogicalOperator &op, int ObLogDelUpd::find_pdml_part_id_producer(ObLogicalOperator *op,
const uint64_t loc_tid, const uint64_t loc_tid,
const uint64_t ref_tid, const uint64_t ref_tid,
ObLogicalOperator *&producer) ObLogExchange *&producer,
ObLogTableScan *&src_tsc)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
producer = NULL; if (OB_ISNULL(op)) {
OZ(check_stack_overflow()); ret = OB_ERR_UNEXPECTED;
if (OB_SUCC(ret)) { LOG_WARN("unexpected null", K(ret), K(op));
if (op.get_type() == log_op_def::LOG_EXCHANGE) { } else if (op->is_dml_operator()) {
ObLogExchange &log_ex = static_cast<ObLogExchange &>(op); // for pdml insert split by update, generate partition id by exchange above delete
if (log_ex.is_producer() && log_ex.get_repartition_ref_table_id() == ref_tid } else if (op->get_type() == log_op_def::LOG_TABLE_SCAN) {
&& log_ex.get_repartition_table_id() == loc_tid) { // PDML partition id expr在table scan分配的逻辑
producer = &op; // pdml table scan分配partition id expr的producer
} // table scan中分配partition id expr的producer的逻辑比较特殊:
} else if (op.get_type() == log_op_def::LOG_TABLE_SCAN) { // 分配partition id的时候,需要保证partition id expr对应的table id与table
// PDML partition id expr在table scan分配的逻辑 // scan的table id是相同的
// pdml table scan分配partition id expr的producer // 对应insert的dml操作,例如:insert into t1 select from t1,
// table scan中分配partition id expr的producer的逻辑比较特殊 // 产生的计划如下
// 分配partition id的时候,需要保证partition id expr对应的table id与table // insert
// scan的table id是相同的 // subplan
// 对应insert的dml操作,例如:insert into t1 select from t1, // GI
// 产生的计划如下: // TSC
// insert // ....
// subplan //
// GI // 这种情况下,如果给TSC算子分配partition idexpr,那么根据表达式分配的框架,
// TSC // 其会被裁剪掉,因此目前insert与subplan之间会添加一个EX算子.
// .... // 后期会进行优化,如果insert与subplan是一个full partition wise
// // join,那么就在insert算子上分配一个GI算子,目前先使用在subplan上分配EX算子的方式实现
// 这种情况下,如果给TSC算子分配partition idexpr,那么根据表达式分配的框架, ObLogTableScan *tsc = static_cast<ObLogTableScan*>(op);
// 其会被裁剪掉,因此目前insert与subplan之间会添加一个EX算子. if (loc_tid == tsc->get_table_id() &&
// 后期会进行优化,如果insert与subplan是一个full partition wise ref_tid == (tsc->get_is_index_global() ? tsc->get_index_table_id() : tsc->get_ref_table_id())) {
// join,那么就在insert算子上分配一个GI算子,目前先使用在subplan上分配EX算子的方式实现 src_tsc = tsc;
ObLogTableScan &tsc = static_cast<ObLogTableScan &>(op); producer = NULL;
if (loc_tid == tsc.get_table_id() &&
ref_tid == (tsc.get_is_index_global() ? tsc.get_index_table_id() : tsc.get_ref_table_id())) {
producer = &op;
}
} }
for (int64_t i = 0; OB_SUCC(ret) && NULL == producer && i < op.get_num_of_child(); i++) { } else {
if (OB_ISNULL(op.get_child(i))) { if (OB_SUCC(ret) && NULL == producer && op->get_type() == log_op_def::LOG_EXCHANGE
ret = OB_ERR_UNEXPECTED; && static_cast<ObLogExchange*>(op)->is_producer()) {
LOG_WARN("null child", K(ret)); // find the first exchange below dml, use this exchange generate partiton id for pdml insert
} else if (log_op_def::LOG_JOIN == op.get_type()) { producer = static_cast<ObLogExchange*>(op);
ObLogJoin &join_op = static_cast<ObLogJoin&>(op); }
if (IS_LEFT_SEMI_ANTI_JOIN(join_op.get_join_type()) && for (int64_t i = 0; OB_SUCC(ret) && NULL == src_tsc && i < op->get_num_of_child(); i++) {
second_child == i) { if (OB_FAIL(SMART_CALL(find_pdml_part_id_producer(op->get_child(i), loc_tid, ref_tid, producer, src_tsc)))) {
continue;
} else if (IS_RIGHT_SEMI_ANTI_JOIN(join_op.get_join_type()) &&
first_child == i) {
continue;
}
if (OB_FAIL(find_pdml_part_id_producer(*op.get_child(i), loc_tid, ref_tid, producer))) {
LOG_WARN("find pdml part id producer failed", K(ret));
}
} else if (OB_FAIL(find_pdml_part_id_producer(*op.get_child(i), loc_tid, ref_tid, producer))) {
LOG_WARN("find pdml part id producer failed", K(ret)); LOG_WARN("find pdml part id producer failed", K(ret));
} }
} }
if (OB_SUCC(ret) && NULL != src_tsc && op->get_type() == log_op_def::LOG_EXCHANGE
&& static_cast<ObLogExchange*>(op)->is_producer()) {
// generate partiton id by exchange above dml target table scan
producer = static_cast<ObLogExchange*>(op);
}
} }
return ret; return ret;
} }

View File

@ -385,10 +385,11 @@ protected:
// The pseudo partition_id for PDML may be produced by repart exchange or TSC. // The pseudo partition_id for PDML may be produced by repart exchange or TSC.
// set %producer to NULL if not found // set %producer to NULL if not found
static int find_pdml_part_id_producer(ObLogicalOperator &op, static int find_pdml_part_id_producer(ObLogicalOperator *op,
const uint64_t loc_tid, const uint64_t loc_tid,
const uint64_t ref_tid, const uint64_t ref_tid,
ObLogicalOperator *&producer); ObLogExchange *&producer,
ObLogTableScan *&src_tsc);
virtual int get_plan_item_info(PlanText &plan_text, virtual int get_plan_item_info(PlanText &plan_text,
ObSqlPlanItem &plan_item) override; ObSqlPlanItem &plan_item) override;