patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -14,51 +14,41 @@
#include "sql/optimizer/ob_log_for_update.h"
#include "sql/optimizer/ob_log_plan.h"
#include "sql/optimizer/ob_optimizer_util.h"
#include "sql/optimizer/ob_opt_est_cost.h"
#include "sql/optimizer/ob_log_table_scan.h"
using namespace oceanbase;
using namespace sql;
using namespace oceanbase::common;
ObLogForUpdate::ObLogForUpdate(ObLogPlan& plan)
: ObLogDelUpd(plan), skip_locked_(false), wait_ts_(-1), lock_tables_(), rowkeys_()
ObLogForUpdate::ObLogForUpdate(ObLogPlan &plan)
: ObLogicalOperator(plan),
skip_locked_(false),
is_multi_part_dml_(false),
gi_charged_(false),
wait_ts_(-1),
lock_rownum_(NULL),
index_dml_info_()
{}
const char* ObLogForUpdate::get_name() const
{
const char *ret = "NOT SET";
if (is_multi_part_dml()) {
return "MULTI FOR UPDATE";
ret = "DISTRIBUTED FOR UPDATE";
} else {
return "FOR UPDATE";
}
}
int ObLogForUpdate::copy_without_child(ObLogicalOperator*& out)
{
int ret = OB_SUCCESS;
ObLogicalOperator* op = NULL;
ObLogForUpdate* for_update = NULL;
out = NULL;
if (OB_FAIL(clone(op))) {
LOG_WARN("failed to clone ObLogSubplanScan", K(ret));
} else if (OB_ISNULL(for_update = static_cast<ObLogForUpdate*>(op))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to cast ObLogicalOperaotr* to ObLogForUpdate*", K(ret));
} else if (OB_FAIL(for_update->lock_tables_.assign(lock_tables_))) {
LOG_WARN("failed to assign lock tables", K(ret));
} else if (OB_FAIL(for_update->rowkeys_.assign(rowkeys_))) {
LOG_WARN("failed to assign rowkey exprs", K(ret));
} else {
for_update->set_wait_ts(get_wait_ts());
for_update->set_skip_locked(is_skip_locked());
out = for_update;
ret = "FOR UPDATE";
}
return ret;
}
int ObLogForUpdate::print_my_plan_annotation(char* buf, int64_t& buf_len, int64_t& pos, ExplainType type)
int ObLogForUpdate::print_my_plan_annotation(char *buf,
int64_t &buf_len,
int64_t &pos,
ExplainType type)
{
int ret = OB_SUCCESS;
ObDMLStmt* stmt = NULL;
const ObDMLStmt *stmt = NULL;
UNUSED(type);
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
ret = OB_ERR_UNEXPECTED;
@ -66,112 +56,186 @@ int ObLogForUpdate::print_my_plan_annotation(char* buf, int64_t& buf_len, int64_
} else if (OB_FAIL(BUF_PRINTF(", lock tables"))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < lock_tables_.count(); ++i) {
uint64_t table_id = lock_tables_.at(i);
TableItem* table = NULL;
if (OB_ISNULL(table = stmt->get_table_item_by_id(table_id))) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_dml_info_.count(); ++i) {
TableItem *table = NULL;
if (OB_ISNULL(index_dml_info_.at(i)) ||
OB_ISNULL(table = stmt->get_table_item_by_id(index_dml_info_.at(i)->table_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table item is not found", K(ret), K(table_id));
LOG_WARN("index dml info is null", K(ret), K(index_dml_info_.at(i)), K(table));
} else if (OB_FAIL(BUF_PRINTF("%c%.*s%c",
i == 0 ? '(' : ' ',
table->get_table_name().length(),
table->get_table_name().ptr(),
i == lock_tables_.count() - 1 ? ')' : ','))) {
i == 0 ? '(' : ' ',
table->get_table_name().length(),
table->get_table_name().ptr(),
i == index_dml_info_.count() - 1 ? ')' : ','))) {
LOG_WARN("failed to print lock table name", K(ret));
}
}
return ret;
}
int ObLogForUpdate::allocate_expr_pre(ObAllocExprContext& ctx)
int ObLogForUpdate::compute_sharding_info()
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 4> dep_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < lock_tables_.count(); ++i) {
ObSEArray<ObColumnRefRawExpr*, 4> rowkeys;
ObSEArray<ObRawExpr*, 4> part_keys;
ObRawExpr* calc_part_expr = NULL;
if (OB_FAIL(get_rowkey_exprs(lock_tables_.at(i), rowkeys))) {
LOG_WARN("failed to get rowkey exprs", K(ret));
} else if (OB_FAIL(append(dep_exprs, rowkeys))) {
LOG_WARN("failed to get rowkey exprs", K(ret));
} else if (!is_multi_part_dml()) {
// do nothing
} else if (OB_FAIL(get_part_columns(lock_tables_.at(i), part_keys))) {
LOG_WARN("failed to get partition columns", K(ret));
} else if (OB_FAIL(append(dep_exprs, part_keys))) {
LOG_WARN("failed to get partition keys", K(ret));
} else if (OB_FAIL(create_calc_part_expr(lock_tables_.at(i), calc_part_expr))) {
LOG_WARN("failed to create calc part expr", K(ret));
} else if (OB_FAIL(calc_part_id_exprs_.push_back(calc_part_expr))) {
LOG_WARN("failed to append calc part id expr", K(ret));
}
ObLogicalOperator *child = NULL;
if (OB_ISNULL(child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(child), K(ret));
} else if (OB_FAIL(ObLogicalOperator::compute_sharding_info())) {
LOG_WARN("failed to compute sharding info", K(ret));
} else if (OB_ISNULL(get_sharding())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
is_partition_wise_ = !is_multi_part_dml_ && !child->is_exchange_allocated() &&
get_sharding()->is_distributed() &&
NULL != get_sharding()->get_phy_table_location_info();
}
for (int64_t i = 0; OB_SUCC(ret) && i < dep_exprs.count(); ++i) {
if (OB_ISNULL(dep_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("dependant expr is null", K(ret));
return ret;
}
int ObLogForUpdate::allocate_granule_pre(AllocGIContext &ctx)
{
return pw_allocate_granule_pre(ctx);
}
int ObLogForUpdate::allocate_granule_post(AllocGIContext &ctx)
{
int ret = OB_SUCCESS;
bool is_partition_wise_state = ctx.is_in_partition_wise_state();
if (OB_ISNULL(get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(pw_allocate_granule_post(ctx))){ // 分配完GI以后,会对ctx的状态进行清理
LOG_WARN("failed to allocate pw gi post", K(ret));
} else {
if (is_partition_wise_state && ctx.is_op_set_pw(this)) {
ObSEArray<ObLogicalOperator *, 2> tsc_ops;
if (OB_FAIL(find_all_tsc(tsc_ops, this))) {
LOG_WARN("failed to find all tsc", K(ret));
} else if (tsc_ops.count() < 1){
// do nothing
set_gi_above(true);
} else {
// tsc op与当前dml算子都需要set gi above
ARRAY_FOREACH(tsc_ops, idx) {
ObLogTableScan *tsc_op = static_cast<ObLogTableScan*>(tsc_ops.at(idx));
tsc_op->set_gi_above(true);
}
set_gi_above(true);
}
} else {
dep_exprs.at(i)->set_explicited_reference();
LOG_TRACE("not allocate dml gi for px",
K(ret), K(ctx), K(ctx.is_op_set_pw(this)));
}
}
if (OB_SUCC(ret) && OB_FAIL(add_exprs_to_ctx(ctx, dep_exprs))) {
LOG_WARN("failed to add exprs to context", K(ret));
}
return ret;
}
int ObLogForUpdate::check_output_dep_specific(ObRawExprCheckDep& checker)
int ObLogForUpdate::get_op_exprs(ObIArray<ObRawExpr*> &all_exprs)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 4> dep_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < lock_tables_.count(); ++i) {
ObSEArray<ObColumnRefRawExpr*, 4> rowkeys;
ObSEArray<ObRawExpr*, 4> part_keys;
if (OB_FAIL(get_rowkey_exprs(lock_tables_.at(i), rowkeys))) {
LOG_WARN("failed to get rowkey exprs", K(ret));
} else if (OB_FAIL(append(dep_exprs, rowkeys))) {
LOG_WARN("failed to append input exprs", K(ret));
} else if (!is_multi_part_dml()) {
// do nothing
} else if (OB_FAIL(get_part_columns(lock_tables_.at(i), part_keys))) {
LOG_WARN("failed to get partition columns", K(ret));
} else if (OB_FAIL(append(dep_exprs, part_keys))) {
LOG_WARN("failed to append partition keys", K(ret));
}
if (is_multi_part_dml() && OB_FAIL(generate_multi_part_partition_id_expr())) {
LOG_WARN("failed to generate update expr", K(ret));
} else if (OB_FAIL(get_for_update_dependant_exprs(all_exprs))) {
LOG_WARN("failed to get for update dependant exprs", K(ret));
} else if (NULL != lock_rownum_ && OB_FAIL(all_exprs.push_back(lock_rownum_))) {
LOG_WARN("failed to push back exprs", K(ret));
} else if (OB_FAIL(ObLogicalOperator::get_op_exprs(all_exprs))) {
LOG_WARN("failed to get op exprs", K(ret));
} else { /*do nothing*/ }
return ret;
}
int ObLogForUpdate::generate_multi_part_partition_id_expr()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(get_stmt()) || OB_ISNULL(get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(get_stmt()), K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < dep_exprs.count(); ++i) {
if (OB_ISNULL(dep_exprs.at(i))) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_dml_info_.count(); ++i) {
const TableItem *table_item = NULL;
ObRawExpr *part_expr = NULL;
if (OB_ISNULL(index_dml_info_.at(i)) ||
OB_ISNULL(table_item = get_stmt()->get_table_item_by_id(
index_dml_info_.at(i)->table_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("part expr is null", K(ret));
} else if (OB_FAIL(checker.check(*dep_exprs.at(i)))) {
LOG_WARN("failed to check part key expr", K(ret));
LOG_WARN("get unexpected null", K(ret), K(index_dml_info_.at(i)), K(table_item));
} else if (OB_FAIL(get_plan()->gen_calc_part_id_expr(table_item->table_id_,
table_item->ref_id_,
CALC_PARTITION_TABLET_ID,
part_expr))) {
LOG_WARN("failed to gen calc part id expr", K(ret));
} else if (OB_ISNULL(part_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
index_dml_info_.at(i)->old_part_id_expr_ = part_expr;
}
}
return ret;
}
uint64_t ObLogForUpdate::hash(uint64_t seed) const
int ObLogForUpdate::get_for_update_dependant_exprs(ObIArray<ObRawExpr*> &dep_exprs)
{
seed = do_hash(skip_locked_, seed);
seed = do_hash(wait_ts_, seed);
HASH_ARRAY(lock_tables_, seed);
seed = ObLogicalOperator::hash(seed);
return seed;
int ret = OB_SUCCESS;
if (OB_ISNULL(get_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
const TableItem *table_item = NULL;
ObSEArray<ObRawExpr*, 4> part_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < index_dml_info_.count(); i++) {
part_exprs.reset();
if (OB_ISNULL(index_dml_info_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index dml info is null", K(ret));
} else if (OB_FAIL(append(dep_exprs, index_dml_info_.at(i)->column_exprs_))) {
LOG_WARN("failed to append rowkey expr", K(ret));
} else if (!is_multi_part_dml()) {
/*do nothing*/
} else if (NULL != index_dml_info_.at(i)->old_part_id_expr_ &&
OB_FAIL(dep_exprs.push_back(index_dml_info_.at(i)->old_part_id_expr_))) {
LOG_WARN("failed to push back old partition id expr", K(ret));
} else if (OB_ISNULL(table_item = get_stmt()->get_table_item_by_id(
index_dml_info_.at(i)->table_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(get_part_column_exprs(table_item->table_id_,
table_item->ref_id_,
part_exprs))) {
LOG_WARN("failed to get partition exprs", K(ret));
} else if (OB_FAIL(append_array_no_dup(dep_exprs, part_exprs))) {
LOG_WARN("failed to append exprs", K(ret));
} else { /*do nothing*/ }
}
// mark expr reference
for (int64_t i = 0; OB_SUCC(ret) && i < dep_exprs.count(); i++) {
if (OB_ISNULL(dep_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
dep_exprs.at(i)->set_explicited_reference();
}
}
}
return ret;
}
int ObLogForUpdate::est_cost()
{
int ret = OB_SUCCESS;
ObLogicalOperator* first_child = NULL;
if (OB_ISNULL(first_child = get_child(ObLogicalOperator::first_child))) {
ObLogicalOperator *first_child = NULL;
if (OB_ISNULL(get_plan()) ||
OB_ISNULL(first_child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("first child is null", K(ret));
} else {
set_op_cost(0);
set_cost(first_child->get_cost());
// todo: refine for update cost
ObOptimizerContext &opt_ctx = get_plan()->get_optimizer_context();
set_op_cost(ObOptEstCost::cost_get_rows(first_child->get_card(), opt_ctx.get_cost_model_type()));
set_cost(first_child->get_cost() + op_cost_);
set_card(first_child->get_card());
set_width(first_child->get_width());
}
return ret;
}
@ -179,7 +243,7 @@ int ObLogForUpdate::est_cost()
int ObLogForUpdate::compute_op_ordering()
{
int ret = OB_SUCCESS;
ObLogicalOperator* child = NULL;
ObLogicalOperator *child = NULL;
if (OB_ISNULL(child = get_child(first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Child is null", K(ret));
@ -189,38 +253,14 @@ int ObLogForUpdate::compute_op_ordering()
return ret;
}
bool ObLogForUpdate::modify_multi_tables() const
{
return lock_tables_.count() > 1;
}
uint64_t ObLogForUpdate::get_target_table_id() const
{
uint64_t target_table_id = OB_INVALID_ID;
if (lock_tables_.count() == 1) {
target_table_id = lock_tables_.at(0);
}
return target_table_id;
}
int ObLogForUpdate::add_for_update_table(uint64_t table_id, const ObIArray<ObColumnRefRawExpr*>& keys)
{
int ret = OB_SUCCESS;
if (OB_FAIL(lock_tables_.push_back(table_id))) {
LOG_WARN("failed to push back table id", K(ret));
} else if (OB_FAIL(append(rowkeys_, keys))) {
LOG_WARN("failed to append rowkey exprs", K(ret));
}
return ret;
}
int ObLogForUpdate::get_table_columns(const uint64_t table_id, ObIArray<ObColumnRefRawExpr*>& table_cols) const
int ObLogForUpdate::get_table_columns(const uint64_t table_id,
ObIArray<ObColumnRefRawExpr *> &table_cols) const
{
int ret = OB_SUCCESS;
if (OB_ISNULL(get_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt is null", K(ret));
} else if (OB_FAIL(get_stmt()->get_column_exprs(table_id, table_cols))) {
} else if (OB_FAIL(get_stmt()->get_column_exprs(table_id, table_cols))) {
LOG_WARN("failed to get column exprs", K(ret));
}
for (int64_t i = table_cols.count() - 1; OB_SUCC(ret) && i >= 0; --i) {
@ -236,96 +276,58 @@ int ObLogForUpdate::get_table_columns(const uint64_t table_id, ObIArray<ObColumn
return ret;
}
int ObLogForUpdate::get_rowkey_exprs(const uint64_t table_id, ObIArray<ObColumnRefRawExpr*>& rowkey) const
int ObLogForUpdate::get_rowkey_exprs(const uint64_t table_id,
ObIArray<ObColumnRefRawExpr *> &rowkey) const
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < rowkeys_.count(); ++i) {
ObColumnRefRawExpr* col = NULL;
if (OB_ISNULL(col = rowkeys_.at(i))) {
for (int64_t i = 0; OB_SUCC(ret) && i < index_dml_info_.count(); ++i) {
if (OB_ISNULL(index_dml_info_.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("rowkey expr is null", K(ret));
} else if (col->get_table_id() != table_id) {
LOG_WARN("index dml info is null", K(ret));
} else if (index_dml_info_.at(i)->table_id_ != table_id) {
// do nothing
} else if (OB_FAIL(rowkey.push_back(col))) {
LOG_WARN("failed to push back col expr", K(ret));
}
}
return ret;
}
int ObLogForUpdate::get_part_columns(const uint64_t table_id, ObIArray<ObRawExpr*>& part_cols) const
{
int ret = OB_SUCCESS;
const TableItem* table = NULL;
ObRawExpr* part_expr = NULL;
if (OB_ISNULL(get_stmt()) || OB_ISNULL(table = get_stmt()->get_table_item_by_id(table_id))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt is null", K(ret), K(table));
} else if (NULL == (part_expr = get_stmt()->get_part_expr(table->table_id_, table->ref_id_))) {
// do nothing
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(part_expr, part_cols))) {
LOG_WARN("failed to extract column exprs", K(ret));
} else if (NULL == (part_expr = get_stmt()->get_subpart_expr(table->table_id_, table->ref_id_))) {
// do nothing
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(part_expr, part_cols))) {
LOG_WARN("failed to extract column exprs", K(ret));
}
return ret;
}
int ObLogForUpdate::create_calc_part_expr(const uint64_t table_id, ObRawExpr*& calc_part_expr)
{
int ret = OB_SUCCESS;
const TableItem* table = NULL;
if (OB_ISNULL(get_stmt()) || OB_ISNULL(table = get_stmt()->get_table_item_by_id(table_id))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt is invalid", K(ret), K(get_stmt()), K(table));
} else if (OB_FAIL(gen_calc_part_id_expr(table_id, table->ref_id_, calc_part_expr))) {
LOG_WARN("failed to gen calc part id expr", K(ret));
}
return ret;
}
int ObLogForUpdate::get_calc_part_expr(const uint64_t table_id, ObRawExpr*& calc_part_expr) const
{
int ret = OB_SUCCESS;
calc_part_expr = NULL;
if (OB_UNLIKELY(lock_tables_.count() != calc_part_id_exprs_.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("calc part expr array is invalid", K(ret), K(lock_tables_.count()), K(calc_part_id_exprs_.count()));
}
for (int64_t i = 0; OB_SUCC(ret) && i < lock_tables_.count(); ++i) {
if (lock_tables_.at(i) == table_id) {
calc_part_expr = calc_part_id_exprs_.at(i);
} else if (OB_FAIL(append(rowkey, index_dml_info_.at(i)->column_exprs_))) {
LOG_WARN("failed to append rowkey expr", K(ret));
} else {
break;
}
}
return ret;
}
int ObLogForUpdate::is_rowkey_nullable(const uint64_t table_id, bool& is_nullable) const
int ObLogForUpdate::is_rowkey_nullable(const uint64_t table_id, bool &is_nullable) const
{
int ret = OB_SUCCESS;
is_nullable = false;
if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(get_stmt(), table_id, is_nullable))) {
if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(get_stmt(),
table_id,
is_nullable))) {
LOG_WARN("failed to check is table on null side", K(ret));
}
return ret;
}
int ObLogForUpdate::inner_append_not_produced_exprs(ObRawExprUniqueSet& raw_exprs) const
bool ObLogForUpdate::is_multi_table_skip_locked()
{
bool is_multi_table_skip_locked = false;
if (index_dml_info_.count() > 1 && is_skip_locked()) {
is_multi_table_skip_locked = true;
}
return is_multi_table_skip_locked;
}
int ObLogForUpdate::copy_part_expr_pre(CopyPartExprCtx &ctx)
{
int ret = OB_SUCCESS;
ObLogicalOperator* child = NULL;
if (OB_ISNULL(child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child is null", K(ret), K(child));
} else if (OB_FAIL(raw_exprs.append(child->get_output_exprs()))) {
LOG_WARN("failed to append child output exprs", K(ret));
} else if (OB_FAIL(raw_exprs.append(get_output_exprs()))) {
LOG_WARN("failed to append output exprs", K(ret));
} else if (OB_FAIL(raw_exprs.append(calc_part_id_exprs_))) {
LOG_WARN("failed to append calc part id expr", K(ret));
for (int64_t i = 0; OB_SUCC(ret) && i < index_dml_info_.count(); ++i) {
IndexDMLInfo *dml_info = index_dml_info_.at(i);
if (OB_ISNULL(dml_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(dml_info));
} else if (NULL != dml_info->old_part_id_expr_ &&
OB_FAIL(copy_part_expr(ctx, dml_info->old_part_id_expr_))) {
LOG_WARN("failed to copy part expr", K(ret));
}
}
return ret;
}
}