add pq_gby/pq_distinct hint, fix some outline bug
This commit is contained in:
parent
cdaf7ee37d
commit
38896ca913
@ -2588,6 +2588,11 @@ typedef enum ObItemType
|
||||
//restore sts
|
||||
T_RESTORE_WITH_CONFIG_LIST = 4732,
|
||||
T_STS_CREDENTIAL = 4733,
|
||||
// optimizer hint
|
||||
T_PQ_GBY_HINT = 4734,
|
||||
T_PQ_DISTINCT_HINT = 4735,
|
||||
T_DISTRIBUTE_BASIC = 4736,
|
||||
|
||||
T_MAX //Attention: add a new type before T_MAX
|
||||
} ObItemType;
|
||||
|
||||
|
@ -9758,7 +9758,9 @@ int ObJoinOrder::get_distributed_join_method(Path &left_path,
|
||||
ObShardingInfo *left_sharding = NULL;
|
||||
ObShardingInfo *right_sharding = NULL;
|
||||
distributed_methods = path_info.distributed_methods_;
|
||||
bool use_shared_hash_join = right_path.parallel_ > ObGlobalHint::DEFAULT_PARALLEL;
|
||||
const bool is_force_dist_method = !path_info.ignore_hint_
|
||||
&& (distributed_methods == get_dist_algo(distributed_methods));
|
||||
bool use_shared_hash_join = false;
|
||||
ObSQLSessionInfo *session = NULL;
|
||||
int64_t max_path_parallel = max(left_path.parallel_, right_path.parallel_);
|
||||
can_slave_mapping =
|
||||
@ -9773,7 +9775,7 @@ int ObJoinOrder::get_distributed_join_method(Path &left_path,
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(get_plan()), K(left_sharding),
|
||||
K(right_sharding), K(left_path.parent_), K(ret));
|
||||
} else if (use_shared_hash_join && OB_FAIL(session->get_px_shared_hash_join( use_shared_hash_join))) {
|
||||
} else if (OB_FAIL(session->get_px_shared_hash_join(use_shared_hash_join))) {
|
||||
LOG_WARN("get force parallel ddl dop failed", K(ret));
|
||||
} else if (HASH_JOIN == join_algo && is_naaj) {
|
||||
distributed_methods &= ~DIST_PARTITION_WISE;
|
||||
@ -9791,14 +9793,20 @@ int ObJoinOrder::get_distributed_join_method(Path &left_path,
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (HASH_JOIN == join_algo) {
|
||||
if (use_shared_hash_join) {
|
||||
distributed_methods &= ~DIST_BROADCAST_NONE;
|
||||
distributed_methods &= ~DIST_ALL_NONE;
|
||||
OPT_TRACE("shared hash join will not use BROADCAST");
|
||||
if (use_shared_hash_join && right_path.parallel_ > ObGlobalHint::DEFAULT_PARALLEL) {
|
||||
if (is_force_dist_method && (DIST_BROADCAST_NONE == distributed_methods
|
||||
|| DIST_ALL_NONE == distributed_methods)) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
distributed_methods &= ~DIST_BROADCAST_NONE;
|
||||
distributed_methods &= ~DIST_ALL_NONE;
|
||||
OPT_TRACE("shared hash join will not use BROADCAST");
|
||||
}
|
||||
if (IS_LEFT_STYLE_JOIN(path_info.join_type_)) {
|
||||
distributed_methods &= ~DIST_BC2HOST_NONE;
|
||||
}
|
||||
} else {
|
||||
use_shared_hash_join = false;
|
||||
distributed_methods &= ~DIST_BC2HOST_NONE;
|
||||
OPT_TRACE("hash join will not use BC2HOST");
|
||||
}
|
||||
|
@ -348,6 +348,13 @@ int ObLogDistinct::print_outline_data(PlanText &plan_text)
|
||||
qb_name.length(),
|
||||
qb_name.ptr()))) {
|
||||
LOG_WARN("fail to print buffer", K(ret), K(buf), K(buf_len), K(pos));
|
||||
} else if (NULL != op || is_partition_wise()) {
|
||||
ObPQHint pq_hint(T_PQ_DISTINCT_HINT);
|
||||
pq_hint.set_qb_name(qb_name);
|
||||
pq_hint.set_dist_method(is_partition_wise() ? T_DISTRIBUTE_NONE : T_DISTRIBUTE_HASH);
|
||||
if (OB_FAIL(pq_hint.print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print pq hint", K(ret), K(pq_hint));
|
||||
}
|
||||
} else {/*do nothing*/}
|
||||
return ret;
|
||||
}
|
||||
@ -362,7 +369,8 @@ int ObLogDistinct::print_used_hint(PlanText &plan_text)
|
||||
LOG_WARN("unexpected NULL", K(ret), K(get_plan()));
|
||||
} else {
|
||||
const ObHint *use_hash = get_plan()->get_log_plan_hint().get_normal_hint(T_USE_HASH_DISTINCT);
|
||||
const ObHint *pushdown = get_plan()->get_log_plan_hint().get_normal_hint(T_DISTINCT_PUSHDOWN);
|
||||
const ObHint *pushdown_hint = get_plan()->get_log_plan_hint().get_normal_hint(T_DISTINCT_PUSHDOWN);
|
||||
const ObPQHint *pq_hint = dynamic_cast<const ObPQHint*>(get_plan()->get_log_plan_hint().get_normal_hint(T_PQ_DISTINCT_HINT));
|
||||
if (NULL != use_hash) {
|
||||
bool match_hint = (HASH_AGGREGATE == algo_ && use_hash->is_enable_hint())
|
||||
|| (MERGE_AGGREGATE == algo_ && use_hash->is_disable_hint());
|
||||
@ -370,7 +378,7 @@ int ObLogDistinct::print_used_hint(PlanText &plan_text)
|
||||
LOG_WARN("failed to print used hint for group by", K(ret), K(*use_hash));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && NULL != pushdown) {
|
||||
if (OB_SUCC(ret) && (NULL != pushdown_hint || NULL != pq_hint)) {
|
||||
const ObLogicalOperator *child = NULL;
|
||||
const ObLogicalOperator *op = NULL;
|
||||
if (OB_ISNULL(child = get_child(ObLogicalOperator::first_child))) {
|
||||
@ -378,12 +386,14 @@ int ObLogDistinct::print_used_hint(PlanText &plan_text)
|
||||
LOG_WARN("unexpected NULL", K(ret), K(child));
|
||||
} else if (OB_FAIL(child->get_pushdown_op(log_op_def::LOG_DISTINCT, op))) {
|
||||
LOG_WARN("failed to get push down distinct", K(ret));
|
||||
} else {
|
||||
bool match_hint = NULL == op ? pushdown->is_disable_hint()
|
||||
: pushdown->is_enable_hint();
|
||||
if (match_hint && OB_FAIL(pushdown->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used hint for group by", K(ret), K(*pushdown));
|
||||
}
|
||||
} else if (NULL != pushdown_hint && (NULL == op ? pushdown_hint->is_disable_hint() : pushdown_hint->is_enable_hint())
|
||||
&& OB_FAIL(pushdown_hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used hint for group by", K(ret), KPC(pushdown_hint));
|
||||
} else if (NULL != pq_hint
|
||||
&& ((NULL != op && pq_hint->is_force_dist_hash())
|
||||
|| (is_partition_wise() && pq_hint->is_force_partition_wise()))
|
||||
&& OB_FAIL(pq_hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used hint for pq group by", K(ret), KPC(pq_hint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -532,6 +532,14 @@ int ObLogGroupBy::print_outline_data(PlanText &plan_text)
|
||||
LOG_WARN("failed to print hint", K(ret), K(hint));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && T_DISTRIBUTE_BASIC != dist_method_) {
|
||||
ObPQHint hint(T_PQ_GBY_HINT);
|
||||
hint.set_qb_name(qb_name);
|
||||
hint.set_dist_method(dist_method_);
|
||||
if (OB_FAIL(hint.print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print hint", K(ret), K(hint));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -554,6 +562,10 @@ int ObLogGroupBy::print_used_hint(PlanText &plan_text)
|
||||
&& static_cast<const ObAggHint*>(hint)->force_partition_sort() == use_part_sort_
|
||||
&& OB_FAIL(hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used hint for group by", K(ret), K(*hint));
|
||||
} else if (NULL != (hint = get_plan()->get_log_plan_hint().get_normal_hint(T_PQ_GBY_HINT))
|
||||
&& static_cast<const ObPQHint*>(hint)->is_dist_method_match(dist_method_)
|
||||
&& OB_FAIL(hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used hint for group by", K(ret), K(*hint));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ public:
|
||||
use_hash_aggr_(false),
|
||||
has_push_down_(false),
|
||||
use_part_sort_(false),
|
||||
dist_method_(T_INVALID),
|
||||
is_pushdown_scalar_aggr_(false)
|
||||
{}
|
||||
virtual ~ObLogGroupBy()
|
||||
@ -218,8 +219,17 @@ public:
|
||||
{ return ObRollupStatus::ROLLUP_COLLECTOR == rollup_adaptive_info_.rollup_status_; }
|
||||
inline void set_force_push_down(bool force_push_down)
|
||||
{ force_push_down_ = force_push_down; }
|
||||
void set_group_by_outline_info(bool use_hash_aggr, bool has_push_down, bool use_part_sort = false)
|
||||
{ use_hash_aggr_ = use_hash_aggr; has_push_down_ = has_push_down; use_part_sort_ = use_part_sort; }
|
||||
void set_group_by_outline_info(bool is_basic,
|
||||
bool is_partition_wise,
|
||||
bool use_hash_aggr,
|
||||
bool has_push_down,
|
||||
bool use_part_sort = false)
|
||||
{
|
||||
dist_method_ = is_basic ? T_DISTRIBUTE_BASIC : (is_partition_wise ? T_DISTRIBUTE_NONE : T_DISTRIBUTE_HASH);
|
||||
use_hash_aggr_ = use_hash_aggr;
|
||||
has_push_down_ = has_push_down;
|
||||
use_part_sort_ = use_part_sort;
|
||||
}
|
||||
virtual int get_plan_item_info(PlanText &plan_text,
|
||||
ObSqlPlanItem &plan_item) override;
|
||||
|
||||
@ -265,6 +275,7 @@ private:
|
||||
bool use_hash_aggr_;
|
||||
bool has_push_down_;
|
||||
bool use_part_sort_;
|
||||
ObItemType dist_method_;
|
||||
bool is_pushdown_scalar_aggr_;
|
||||
};
|
||||
} // end of namespace sql
|
||||
|
@ -5201,7 +5201,7 @@ int ObLogPlan::create_three_stage_group_plan(const ObIArray<ObRawExpr*> &group_b
|
||||
helper.rollup_id_expr_))) {
|
||||
LOG_WARN("failed to set rollup parallel info", K(ret));
|
||||
} else {
|
||||
third_group_by->set_group_by_outline_info(HASH_AGGREGATE == second_aggr_algo, true);
|
||||
third_group_by->set_group_by_outline_info(false, false, HASH_AGGREGATE == second_aggr_algo, true);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -5353,36 +5353,70 @@ int ObLogPlan::candi_allocate_scala_group_by(const ObIArray<ObAggFunRawExpr*> &a
|
||||
const bool is_from_povit)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<CandidatePlan, 4> best_plans;
|
||||
ObSEArray<CandidatePlan, 4> groupby_plans;
|
||||
ObSEArray<ObRawExpr*, 1> dummy_exprs;
|
||||
SMART_VAR(GroupingOpHelper, groupby_helper) {
|
||||
if (OB_FAIL(init_groupby_helper(dummy_exprs, dummy_exprs, agg_items,
|
||||
is_from_povit, groupby_helper))) {
|
||||
LOG_WARN("failed to init group by helper", K(ret));
|
||||
} else if (OB_FAIL(get_minimal_cost_candidates(candidates_.candidate_plans_, best_plans))) {
|
||||
LOG_WARN("failed to get minimal cost candidate", K(ret));
|
||||
} else if (OB_FAIL(inner_candi_allocate_scala_group_by(agg_items,
|
||||
having_exprs,
|
||||
groupby_helper,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to inner candi allocate scala group by", K(ret));
|
||||
} else if (!groupby_plans.empty()) {
|
||||
LOG_TRACE("succeed to allocate scala group by using hint", K(groupby_plans.count()), K(groupby_helper));
|
||||
OPT_TRACE("success to generate scala group plan with hint");
|
||||
} else if (OB_FAIL(get_log_plan_hint().check_status())) {
|
||||
LOG_WARN("failed to generate plans with hint", K(ret));
|
||||
} else if (OB_FALSE_IT(groupby_helper.set_ignore_hint())) {
|
||||
} else if (OB_FAIL(inner_candi_allocate_scala_group_by(agg_items,
|
||||
having_exprs,
|
||||
groupby_helper,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to inner candi allocate scala group by", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < best_plans.count(); i++) {
|
||||
OPT_TRACE("generate scala group by for plan:", best_plans.at(i));
|
||||
if (OB_FAIL(create_scala_group_plan(agg_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
best_plans.at(i).plan_tree_))) {
|
||||
LOG_WARN("failed to create scala group by plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
int64_t check_scope = OrderingCheckScope::CHECK_WINFUNC |
|
||||
OrderingCheckScope::CHECK_DISTINCT |
|
||||
OrderingCheckScope::CHECK_SET |
|
||||
OrderingCheckScope::CHECK_ORDERBY;
|
||||
if (OB_FAIL(update_plans_interesting_order_info(best_plans, check_scope))) {
|
||||
LOG_WARN("failed to update plans interesting order info", K(ret));
|
||||
} else if (OB_FAIL(prune_and_keep_best_plans(best_plans))) {
|
||||
LOG_WARN("failed to add plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
LOG_TRACE("succeed to allocate scala group by ignore hint", K(groupby_plans.count()), K(groupby_helper));
|
||||
OPT_TRACE("success to generate scala group plan without hint");
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
int64_t check_scope = OrderingCheckScope::CHECK_WINFUNC |
|
||||
OrderingCheckScope::CHECK_DISTINCT |
|
||||
OrderingCheckScope::CHECK_SET |
|
||||
OrderingCheckScope::CHECK_ORDERBY;
|
||||
if (OB_FAIL(update_plans_interesting_order_info(groupby_plans, check_scope))) {
|
||||
LOG_WARN("failed to update plans interesting order info", K(ret));
|
||||
} else if (OB_FAIL(prune_and_keep_best_plans(groupby_plans))) {
|
||||
LOG_WARN("failed to add plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlan::inner_candi_allocate_scala_group_by(const ObIArray<ObAggFunRawExpr*> &agg_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObIArray<CandidatePlan> &groupby_plans)
|
||||
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<CandidatePlan, 4> best_plans;
|
||||
if (OB_FAIL(get_minimal_cost_candidates(candidates_.candidate_plans_, best_plans))) {
|
||||
LOG_WARN("failed to get minimal cost candidate", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < best_plans.count(); i++) {
|
||||
OPT_TRACE("generate scala group by for plan:", best_plans.at(i));
|
||||
if (OB_FAIL(create_scala_group_plan(agg_items,
|
||||
having_exprs,
|
||||
groupby_helper,
|
||||
best_plans.at(i).plan_tree_))) {
|
||||
LOG_WARN("failed to create scala group by plan", K(ret));
|
||||
} else if (NULL != best_plans.at(i).plan_tree_ &&
|
||||
OB_FAIL(groupby_plans.push_back(best_plans.at(i)))) {
|
||||
LOG_WARN("failed to push merge group by", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -5390,7 +5424,6 @@ int ObLogPlan::candi_allocate_scala_group_by(const ObIArray<ObAggFunRawExpr*> &a
|
||||
|
||||
int ObLogPlan::create_scala_group_plan(const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top)
|
||||
{
|
||||
@ -5411,23 +5444,24 @@ int ObLogPlan::create_scala_group_plan(const ObIArray<ObAggFunRawExpr*> &aggr_it
|
||||
LOG_WARN("failed to push group by into table scan", K(ret));
|
||||
} else if (!top->is_distributed()) {
|
||||
OPT_TRACE("generate scala group plan without pushdown");
|
||||
if (OB_FAIL(allocate_scala_group_by_as_top(top,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
origin_child_card))) {
|
||||
if (!groupby_helper.allow_basic()) {
|
||||
top = NULL;
|
||||
OPT_TRACE("ignore basic scala group by hint");
|
||||
} else if (OB_FAIL(allocate_scala_group_by_as_top(top,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
groupby_helper.is_from_povit_,
|
||||
origin_child_card))) {
|
||||
LOG_WARN("failed to allocate scala group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, false);
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(true, false, false, false);
|
||||
}
|
||||
} else if (!groupby_helper.distinct_exprs_.empty() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(groupby_helper.distinct_exprs_,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check if sharding compatible with distinct expr", K(ret));
|
||||
} else if (groupby_helper.can_three_stage_pushdown_ &&
|
||||
!(is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
!(is_partition_wise && groupby_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt()))) {
|
||||
OPT_TRACE("generate three stage group plan");
|
||||
if (NULL == groupby_helper.aggr_code_expr_ &&
|
||||
OB_FAIL(prepare_three_stage_info(dummy_exprs, dummy_exprs, groupby_helper))) {
|
||||
@ -5447,7 +5481,7 @@ int ObLogPlan::create_scala_group_plan(const ObIArray<ObAggFunRawExpr*> &aggr_it
|
||||
dummy_exprs,
|
||||
aggr_items,
|
||||
dummy_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card,
|
||||
is_partition_wise,
|
||||
@ -5461,11 +5495,11 @@ int ObLogPlan::create_scala_group_plan(const ObIArray<ObAggFunRawExpr*> &aggr_it
|
||||
} else if (OB_FAIL(allocate_scala_group_by_as_top(top,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
origin_child_card))) {
|
||||
LOG_WARN("failed to allocate scala group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, groupby_helper.can_basic_pushdown_ || is_partition_wise);
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, is_partition_wise, false, groupby_helper.can_basic_pushdown_ || is_partition_wise);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5576,6 +5610,9 @@ int ObLogPlan::init_groupby_helper(const ObIArray<ObRawExpr*> &group_exprs,
|
||||
ObSEArray<ObRawExpr*, 4> group_rollup_exprs;
|
||||
bool push_group = false;
|
||||
groupby_helper.is_scalar_group_by_ = true;
|
||||
groupby_helper.is_from_povit_ = is_from_povit;
|
||||
groupby_helper.clear_ignore_hint();
|
||||
groupby_helper.optimizer_features_enable_version_ = get_log_plan_hint().optimizer_features_enable_version_;
|
||||
if (OB_FAIL(candidates_.get_best_plan(best_plan))) {
|
||||
LOG_WARN("failed to get best plan", K(ret));
|
||||
} else if (OB_ISNULL(best_plan) ||
|
||||
@ -5591,7 +5628,10 @@ int ObLogPlan::init_groupby_helper(const ObIArray<ObRawExpr*> &group_exprs,
|
||||
} else if (OB_FAIL(get_log_plan_hint().get_aggregation_info(groupby_helper.force_use_hash_,
|
||||
groupby_helper.force_use_merge_,
|
||||
groupby_helper.force_part_sort_,
|
||||
groupby_helper.force_normal_sort_))) {
|
||||
groupby_helper.force_normal_sort_,
|
||||
groupby_helper.force_basic_,
|
||||
groupby_helper.force_partition_wise_,
|
||||
groupby_helper.force_dist_hash_))) {
|
||||
LOG_WARN("failed to get aggregation info from hint", K(ret));
|
||||
} else if (OB_FAIL(check_storage_groupby_pushdown(aggr_items,
|
||||
group_exprs,
|
||||
@ -5696,18 +5736,24 @@ int ObLogPlan::init_distinct_helper(const ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
ObSQLSessionInfo *session_info = NULL;
|
||||
bool push_distinct = false;
|
||||
distinct_helper.can_basic_pushdown_ = false;
|
||||
distinct_helper.force_use_hash_ = get_log_plan_hint().use_hash_distinct();
|
||||
distinct_helper.force_use_merge_ = get_log_plan_hint().use_merge_distinct();
|
||||
distinct_helper.clear_ignore_hint();
|
||||
distinct_helper.optimizer_features_enable_version_ = get_log_plan_hint().optimizer_features_enable_version_;
|
||||
if (OB_FAIL(candidates_.get_best_plan(best_plan))) {
|
||||
LOG_WARN("failed to get best plan", K(ret));
|
||||
} else if (OB_ISNULL(best_plan) || OB_ISNULL(get_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (get_log_plan_hint().no_pushdown_distinct()) {
|
||||
OPT_TRACE("hint disable pushdown distinct");
|
||||
} else if (OB_FAIL(get_log_plan_hint().get_distinct_info(distinct_helper.force_use_hash_,
|
||||
distinct_helper.force_use_merge_,
|
||||
distinct_helper.force_basic_,
|
||||
distinct_helper.force_partition_wise_,
|
||||
distinct_helper.force_dist_hash_))) {
|
||||
LOG_WARN("failed to get distinct info from hint", K(ret));
|
||||
} else if (OB_FAIL(check_storage_distinct_pushdown(distinct_exprs,
|
||||
distinct_helper.can_storage_pushdown_))) {
|
||||
LOG_WARN("failed to check can storage distinct pushdown", K(ret));
|
||||
} else if (get_log_plan_hint().no_pushdown_distinct()) {
|
||||
OPT_TRACE("hint disable pushdown distinct");
|
||||
} else if (OB_ISNULL(session_info = get_optimizer_context().get_session_info())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(session_info), K(ret));
|
||||
|
@ -485,6 +485,17 @@ public:
|
||||
}
|
||||
virtual ~GroupingOpHelper() {}
|
||||
|
||||
void set_ignore_hint() { ignore_hint_ = true; }
|
||||
void clear_ignore_hint() { ignore_hint_ = false; }
|
||||
inline bool allow_basic() const { return ignore_hint_ || (!force_partition_wise_ && !force_dist_hash_); }
|
||||
inline bool allow_dist_hash() const { return ignore_hint_ || (!force_basic_ && !force_partition_wise_); }
|
||||
inline bool allow_partition_wise(bool parallel_more_than_part_cnt) const
|
||||
{
|
||||
bool disable_by_rule = parallel_more_than_part_cnt && optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2;
|
||||
return ignore_hint_ ? !disable_by_rule
|
||||
: (disable_by_rule ? force_partition_wise_ : (!force_basic_ && !force_dist_hash_));
|
||||
}
|
||||
|
||||
bool can_storage_pushdown_;
|
||||
bool can_basic_pushdown_;
|
||||
bool can_three_stage_pushdown_;
|
||||
@ -493,7 +504,13 @@ public:
|
||||
bool force_use_merge_; // has no_use_hash_aggregation/no_use_hash_distinct hint
|
||||
bool force_part_sort_; // force use partition sort for merge group by
|
||||
bool force_normal_sort_; // disable use partition sort for merge group by
|
||||
bool force_basic_; // pq hint force use basic plan
|
||||
bool force_partition_wise_; // pq hint force use partition wise plan
|
||||
bool force_dist_hash_; // pq hint force use hash distributed method plan
|
||||
bool is_scalar_group_by_;
|
||||
bool is_from_povit_;
|
||||
bool ignore_hint_;
|
||||
uint64_t optimizer_features_enable_version_;
|
||||
ObSEArray<ObRawExpr*, 8> distinct_exprs_;
|
||||
|
||||
// context for three stage group by push down
|
||||
@ -518,7 +535,15 @@ public:
|
||||
K_(can_rollup_pushdown),
|
||||
K_(force_use_hash),
|
||||
K_(force_use_merge),
|
||||
K_(force_part_sort),
|
||||
K_(force_normal_sort),
|
||||
K_(force_basic),
|
||||
K_(force_partition_wise),
|
||||
K_(force_dist_hash),
|
||||
K_(is_scalar_group_by),
|
||||
K_(is_from_povit),
|
||||
K_(ignore_hint),
|
||||
K_(optimizer_features_enable_version),
|
||||
K_(distinct_exprs),
|
||||
K_(pushdown_groupby_columns),
|
||||
K_(group_ndv),
|
||||
@ -675,6 +700,11 @@ public:
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit);
|
||||
|
||||
int inner_candi_allocate_scala_group_by(const ObIArray<ObAggFunRawExpr*> &agg_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObIArray<CandidatePlan> &groupby_plans);
|
||||
|
||||
int prepare_three_stage_info(const ObIArray<ObRawExpr *> &group_by_exprs,
|
||||
const ObIArray<ObRawExpr *> &rollup_exprs,
|
||||
GroupingOpHelper &helper);
|
||||
@ -712,7 +742,6 @@ public:
|
||||
|
||||
int create_scala_group_plan(const ObIArray<ObAggFunRawExpr*> &agg_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top);
|
||||
|
||||
|
@ -265,10 +265,28 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to candi allocate three stage group by", K(ret));
|
||||
} else if (!groupby_plans.empty()) {
|
||||
LOG_TRACE("succeed to allocate three stage group by using hint", K(groupby_plans.count()), K(groupby_helper));
|
||||
OPT_TRACE("success to generate three stage group plan with hint");
|
||||
} else if (OB_FAIL(get_log_plan_hint().check_status())) {
|
||||
LOG_WARN("failed to generate plans with hint", K(ret));
|
||||
} else if (OB_FALSE_IT(groupby_helper.set_ignore_hint())) {
|
||||
} else if (OB_FAIL(candi_allocate_three_stage_group_by(reduce_exprs,
|
||||
group_by_exprs,
|
||||
group_directions,
|
||||
rollup_exprs,
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
groupby_helper,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to candi allocate three stage group by", K(ret));
|
||||
} else {
|
||||
LOG_TRACE("succeed to allocate three stage group by ignore hint", K(groupby_plans.count()), K(groupby_helper));
|
||||
OPT_TRACE("success to generate three stage group plan without hint");
|
||||
}
|
||||
} else if (OB_FAIL(candi_allocate_normal_group_by(reduce_exprs,
|
||||
group_by_exprs,
|
||||
@ -277,9 +295,7 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
rollup_directions,
|
||||
having_exprs,
|
||||
aggr_items,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
false,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to inner allocate normal group by", K(ret));
|
||||
} else if (!groupby_plans.empty()) {
|
||||
@ -287,6 +303,7 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
OPT_TRACE("success to generate group plan with hint");
|
||||
} else if (OB_FAIL(get_log_plan_hint().check_status())) {
|
||||
LOG_WARN("failed to generate plans with hint", K(ret));
|
||||
} else if (OB_FALSE_IT(groupby_helper.set_ignore_hint())) {
|
||||
} else if (OB_FAIL(candi_allocate_normal_group_by(reduce_exprs,
|
||||
group_by_exprs,
|
||||
group_directions,
|
||||
@ -294,9 +311,7 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
rollup_directions,
|
||||
having_exprs,
|
||||
aggr_items,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
true,
|
||||
groupby_plans))) {
|
||||
LOG_WARN("failed to inner allocate normal group by", K(ret));
|
||||
} else {
|
||||
@ -328,7 +343,6 @@ int ObSelectLogPlan::candi_allocate_three_stage_group_by(const ObIArray<ObRawExp
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObIArray<CandidatePlan> &groupby_plans)
|
||||
{
|
||||
@ -344,14 +358,13 @@ int ObSelectLogPlan::candi_allocate_three_stage_group_by(const ObIArray<ObRawExp
|
||||
if (OB_ISNULL(candidate_plan.plan_tree_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (candidate_plan.plan_tree_->is_distributed() && !reduce_exprs.empty() &&
|
||||
OB_FAIL(candidate_plan.plan_tree_->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
} else if (!candidate_plan.plan_tree_->is_distributed() && !groupby_helper.allow_basic()) {
|
||||
OPT_TRACE("ignore basic group by hint");
|
||||
} else if (candidate_plan.plan_tree_->is_distributed() && !reduce_exprs.empty()
|
||||
&& groupby_helper.allow_partition_wise(candidate_plan.plan_tree_->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(candidate_plan.plan_tree_->check_sharding_compatible_with_reduce_expr(reduce_exprs, is_partition_wise))) {
|
||||
LOG_WARN("failed to check if sharding compatible with distinct expr", K(ret));
|
||||
} else if (!candidate_plan.plan_tree_->is_distributed() ||
|
||||
(is_partition_wise &&
|
||||
!(candidate_plan.plan_tree_->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!candidate_plan.plan_tree_->is_distributed() || is_partition_wise) {
|
||||
bool part_sort_valid = !groupby_helper.force_normal_sort_ && !group_by_exprs.empty();
|
||||
bool normal_sort_valid = !groupby_helper.force_part_sort_;
|
||||
if (OB_FAIL(update_part_sort_method(part_sort_valid, normal_sort_valid))) {
|
||||
@ -363,7 +376,6 @@ int ObSelectLogPlan::candi_allocate_three_stage_group_by(const ObIArray<ObRawExp
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
candidate_plan,
|
||||
groupby_plans,
|
||||
@ -393,7 +405,6 @@ int ObSelectLogPlan::candi_allocate_three_stage_group_by(const ObIArray<ObRawExp
|
||||
|
||||
int ObSelectLogPlan::get_valid_aggr_algo(const ObIArray<ObRawExpr*> &group_by_exprs,
|
||||
const GroupingOpHelper &groupby_helper,
|
||||
const bool ignore_hint,
|
||||
bool &use_hash_valid,
|
||||
bool &use_merge_valid,
|
||||
bool &part_sort_valid,
|
||||
@ -401,7 +412,7 @@ int ObSelectLogPlan::get_valid_aggr_algo(const ObIArray<ObRawExpr*> &group_by_ex
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool has_keep_aggr = false;
|
||||
if (ignore_hint) {
|
||||
if (groupby_helper.ignore_hint_) {
|
||||
use_hash_valid = true;
|
||||
use_merge_valid = true;
|
||||
part_sort_valid = true;
|
||||
@ -470,9 +481,7 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
const bool ignore_hint,
|
||||
ObIArray<CandidatePlan> &groupby_plans)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -481,7 +490,7 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
bool use_merge_valid = false;
|
||||
bool part_sort_valid = false;
|
||||
bool normal_sort_valid = false;
|
||||
if (OB_FAIL(get_valid_aggr_algo(group_by_exprs, groupby_helper, ignore_hint,
|
||||
if (OB_FAIL(get_valid_aggr_algo(group_by_exprs, groupby_helper,
|
||||
use_hash_valid, use_merge_valid,
|
||||
part_sort_valid, normal_sort_valid))) {
|
||||
LOG_WARN("failed to get valid aggr algo", K(ret));
|
||||
@ -500,7 +509,6 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
rollup_exprs,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
candidate_plan.plan_tree_))) {
|
||||
LOG_WARN("failed to create hash group by plan", K(ret));
|
||||
@ -543,7 +551,6 @@ int ObSelectLogPlan::candi_allocate_normal_group_by(const ObIArray<ObRawExpr*> &
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
candidate_plan,
|
||||
groupby_plans,
|
||||
@ -572,13 +579,13 @@ int ObSelectLogPlan::should_create_rollup_pushdown_plan(ObLogicalOperator *top,
|
||||
LOG_WARN("logical operator is null", K(ret), K(top), K(session));
|
||||
} else if (rollup_exprs.empty() || !groupby_helper.can_rollup_pushdown_) {
|
||||
// do nothing
|
||||
} else if (top->is_distributed() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
} else if (!top->is_distributed() && !groupby_helper.allow_basic()) {
|
||||
// do nothing
|
||||
} else if (top->is_distributed() && groupby_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check is partition wise", K(ret));
|
||||
} else if (!top->is_distributed() || (is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!top->is_distributed() || is_partition_wise) {
|
||||
// do nothing
|
||||
} else if (NULL == groupby_helper.rollup_id_expr_ &&
|
||||
OB_FAIL(ObRawExprUtils::build_pseudo_rollup_id(get_optimizer_context().get_expr_factory(),
|
||||
@ -715,7 +722,7 @@ int ObSelectLogPlan::create_rollup_pushdown_plan(const ObIArray<ObRawExpr*> &gro
|
||||
groupby_helper.rollup_id_expr_))) {
|
||||
LOG_WARN("failed to set rollup id expr", K(ret));
|
||||
} else {
|
||||
rollup_collector->set_group_by_outline_info(false, true);
|
||||
rollup_collector->set_group_by_outline_info(false, false, false, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -725,7 +732,6 @@ int ObSelectLogPlan::create_hash_group_plan(const ObIArray<ObRawExpr*> &reduce_e
|
||||
const ObIArray<ObRawExpr*> &rollup_exprs,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top)
|
||||
{
|
||||
@ -736,26 +742,28 @@ int ObSelectLogPlan::create_hash_group_plan(const ObIArray<ObRawExpr*> &reduce_e
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(top), K(get_stmt()), K(ret));
|
||||
} else if (OB_FALSE_IT(origin_child_card = top->get_card())) {
|
||||
} else if (top->is_distributed() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
} else if (!top->is_distributed() && !groupby_helper.allow_basic()) {
|
||||
top = NULL;
|
||||
OPT_TRACE("ignore basic hash group by hint");
|
||||
} else if (top->is_distributed() && groupby_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check if sharding compatible", K(ret));
|
||||
} else if (!top->is_distributed() || (is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!top->is_distributed() || is_partition_wise) {
|
||||
bool is_basic = !top->is_distributed();
|
||||
if (OB_FAIL(allocate_group_by_as_top(top,
|
||||
AggregateAlgo::HASH_AGGREGATE,
|
||||
group_by_exprs,
|
||||
rollup_exprs,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to allocate group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(true, false);
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(is_basic, is_partition_wise, true, false);
|
||||
}
|
||||
} else {
|
||||
// allocate push down group by
|
||||
@ -776,7 +784,7 @@ int ObSelectLogPlan::create_hash_group_plan(const ObIArray<ObRawExpr*> &reduce_e
|
||||
dummy_exprs,
|
||||
aggr_items,
|
||||
dummy_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card,
|
||||
is_partition_wise,
|
||||
@ -807,12 +815,12 @@ int ObSelectLogPlan::create_hash_group_plan(const ObIArray<ObRawExpr*> &reduce_e
|
||||
rollup_exprs,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card))) {
|
||||
LOG_WARN("failed to allocate scala group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(true, groupby_helper.can_basic_pushdown_);
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, false, true, groupby_helper.can_basic_pushdown_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -955,7 +963,6 @@ int ObSelectLogPlan::create_merge_group_plan(const ObIArray<ObRawExpr*> &reduce_
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
CandidatePlan &candidate_plan,
|
||||
ObIArray<CandidatePlan> &candidate_plans,
|
||||
@ -973,7 +980,6 @@ int ObSelectLogPlan::create_merge_group_plan(const ObIArray<ObRawExpr*> &reduce_
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
part_sort_mgb_plan.plan_tree_,
|
||||
true,
|
||||
@ -990,7 +996,6 @@ int ObSelectLogPlan::create_merge_group_plan(const ObIArray<ObRawExpr*> &reduce_
|
||||
rollup_directions,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper,
|
||||
candidate_plan.plan_tree_,
|
||||
false,
|
||||
@ -1010,7 +1015,6 @@ int ObSelectLogPlan::inner_create_merge_group_plan(const ObIArray<ObRawExpr*> &r
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top,
|
||||
bool use_part_sort,
|
||||
@ -1086,13 +1090,15 @@ int ObSelectLogPlan::inner_create_merge_group_plan(const ObIArray<ObRawExpr*> &r
|
||||
// 1. need generate partition sort plan, but need not sort
|
||||
// 2. if need sort and no further op needs the output order, not generate merge groupby
|
||||
top = NULL;
|
||||
} else if (top->is_distributed() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
} else if (!top->is_distributed() && !groupby_helper.allow_basic()) {
|
||||
top = NULL;
|
||||
OPT_TRACE("ignore basic group by hint");
|
||||
} else if (top->is_distributed() && groupby_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check if sharding compatible with reduce expr", K(ret));
|
||||
} else if (!top->is_distributed() || (is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!top->is_distributed() || is_partition_wise) {
|
||||
bool is_basic = !top->is_distributed();
|
||||
if (OB_FAIL(try_allocate_sort_as_top(top, sort_keys, need_sort, prefix_pos, part_cnt))) {
|
||||
LOG_WARN("failed to allocate sort as top", K(ret));
|
||||
} else if (OB_FAIL(allocate_group_by_as_top(top,
|
||||
@ -1101,13 +1107,13 @@ int ObSelectLogPlan::inner_create_merge_group_plan(const ObIArray<ObRawExpr*> &r
|
||||
rollup_exprs,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to allocate group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, false, use_part_sort);
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(is_basic, is_partition_wise, false, false, use_part_sort);
|
||||
}
|
||||
} else if (use_part_sort &&
|
||||
OB_FAIL(create_hash_sortkey(part_cnt, sort_keys, hash_sortkey))) {
|
||||
@ -1149,7 +1155,7 @@ int ObSelectLogPlan::inner_create_merge_group_plan(const ObIArray<ObRawExpr*> &r
|
||||
dummy_exprs,
|
||||
aggr_items,
|
||||
dummy_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card,
|
||||
should_pullup_gi,
|
||||
@ -1187,12 +1193,12 @@ int ObSelectLogPlan::inner_create_merge_group_plan(const ObIArray<ObRawExpr*> &r
|
||||
rollup_exprs,
|
||||
aggr_items,
|
||||
having_exprs,
|
||||
is_from_povit,
|
||||
groupby_helper.is_from_povit_,
|
||||
groupby_helper.group_ndv_,
|
||||
origin_child_card))) {
|
||||
LOG_WARN("failed to allocate group by as top", K(ret));
|
||||
} else {
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false,
|
||||
static_cast<ObLogGroupBy*>(top)->set_group_by_outline_info(false, false, false,
|
||||
groupby_helper.can_basic_pushdown_, use_part_sort);
|
||||
}
|
||||
}
|
||||
@ -1440,63 +1446,37 @@ int ObSelectLogPlan::candi_allocate_distinct()
|
||||
LOG_TRACE("distinct exprs is unique, no need distinct", K(distinct_exprs));
|
||||
} else {
|
||||
SMART_VAR(GroupingOpHelper, distinct_helper) {
|
||||
CandidatePlan candidate_plan;
|
||||
ObSEArray<CandidatePlan, 4> distinct_plans;
|
||||
ObSEArray<ObOrderDirection, 4> distinct_directions;
|
||||
ObSEArray<ObAggFunRawExpr*, 1> dummy_items;
|
||||
if (OB_FAIL(init_distinct_helper(distinct_exprs, distinct_helper))) {
|
||||
LOG_WARN("failed to init distinct helper", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::get_default_directions(distinct_exprs.count(),
|
||||
distinct_directions))) {
|
||||
LOG_WARN("failed to generate default directions", K(ret));
|
||||
} else if (distinct_helper.can_storage_pushdown_ &&
|
||||
OB_FAIL(try_push_aggr_into_table_scan(candidates_.candidate_plans_,
|
||||
dummy_items,
|
||||
distinct_exprs))) {
|
||||
LOG_WARN("failed to try push distinct exprs into table scan", K(ret));
|
||||
} else if (OB_FAIL(inner_candi_allocate_distinct(distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs,
|
||||
distinct_plans))) {
|
||||
LOG_WARN("failed to inner candi allocate distinct", K(ret));
|
||||
} else if (!distinct_plans.empty()) {
|
||||
LOG_TRACE("succeed to allocate distinct using hint", K(distinct_plans.count()), K(distinct_helper));
|
||||
OPT_TRACE("success to generate distinct plan with hint");
|
||||
} else if (OB_FAIL(get_log_plan_hint().check_status())) {
|
||||
LOG_WARN("failed to generate plans with hint", K(ret));
|
||||
} else if (OB_FALSE_IT(distinct_helper.set_ignore_hint())) {
|
||||
} else if (OB_FAIL(inner_candi_allocate_distinct(distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs,
|
||||
distinct_plans))) {
|
||||
|
||||
LOG_WARN("failed to inner candi allocate distinct", K(ret));
|
||||
} else {
|
||||
LOG_TRACE("succeed to allocate distinct ignore hint", K(distinct_plans.count()), K(distinct_helper));
|
||||
OPT_TRACE("success to generate distinct plan without hint");
|
||||
}
|
||||
|
||||
// create hash distinct
|
||||
if (OB_SUCC(ret) && !distinct_helper.force_use_merge_) {
|
||||
ObSEArray<CandidatePlan, 16> best_candidates;
|
||||
if (OB_FAIL(get_minimal_cost_candidates(candidates_.candidate_plans_, best_candidates))) {
|
||||
LOG_WARN("failed to get minimal cost candidates", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < best_candidates.count(); i++) {
|
||||
candidate_plan = best_candidates.at(i);
|
||||
OPT_TRACE("generate hash distinct for plan:", candidate_plan);
|
||||
if (OB_FAIL(create_hash_distinct_plan(candidate_plan.plan_tree_,
|
||||
distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs))) {
|
||||
LOG_WARN("failed to create hash distinct plan", K(ret));
|
||||
} else if (OB_FAIL(distinct_plans.push_back(candidate_plan))) {
|
||||
LOG_WARN("failed to push back hash distinct candidate plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create merge distinct plan
|
||||
if (OB_SUCC(ret) && !distinct_helper.force_use_hash_) {
|
||||
bool can_ignore_merge_plan = !(distinct_plans.empty() || distinct_helper.force_use_merge_);
|
||||
bool is_plan_valid = false;
|
||||
for(int64_t i = 0; OB_SUCC(ret) && i < candidates_.candidate_plans_.count(); i++) {
|
||||
candidate_plan = candidates_.candidate_plans_.at(i);
|
||||
OPT_TRACE("generate merge distinct for plan:", candidate_plan);
|
||||
if (OB_FAIL(create_merge_distinct_plan(candidate_plan.plan_tree_,
|
||||
distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs,
|
||||
distinct_directions,
|
||||
is_plan_valid,
|
||||
can_ignore_merge_plan))) {
|
||||
LOG_WARN("failed to allocate merge distinct plan", K(ret));
|
||||
} else if (is_plan_valid && OB_FAIL(distinct_plans.push_back(candidate_plan))) {
|
||||
LOG_WARN("failed to add merge distinct candidate plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
int64_t check_scope = OrderingCheckScope::CHECK_SET | OrderingCheckScope::CHECK_ORDERBY;
|
||||
if (OB_FAIL(update_plans_interesting_order_info(distinct_plans, check_scope))) {
|
||||
@ -1510,6 +1490,56 @@ int ObSelectLogPlan::candi_allocate_distinct()
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSelectLogPlan::inner_candi_allocate_distinct(const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
ObIArray<CandidatePlan> &distinct_plans)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CandidatePlan candidate_plan;
|
||||
// create hash distinct
|
||||
if (OB_SUCC(ret) && !distinct_helper.force_use_merge_) {
|
||||
ObSEArray<CandidatePlan, 16> best_candidates;
|
||||
if (OB_FAIL(get_minimal_cost_candidates(candidates_.candidate_plans_, best_candidates))) {
|
||||
LOG_WARN("failed to get minimal cost candidates", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < best_candidates.count(); i++) {
|
||||
candidate_plan = best_candidates.at(i);
|
||||
OPT_TRACE("generate hash distinct for plan:", candidate_plan);
|
||||
if (OB_FAIL(create_hash_distinct_plan(candidate_plan.plan_tree_,
|
||||
distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs))) {
|
||||
LOG_WARN("failed to create hash distinct plan", K(ret));
|
||||
} else if (NULL != candidate_plan.plan_tree_
|
||||
&& OB_FAIL(distinct_plans.push_back(candidate_plan))) {
|
||||
LOG_WARN("failed to push back hash distinct candidate plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create merge distinct plan
|
||||
if (OB_SUCC(ret) && !distinct_helper.force_use_hash_) {
|
||||
bool can_ignore_merge_plan = !(distinct_plans.empty() || distinct_helper.force_use_merge_);
|
||||
for(int64_t i = 0; OB_SUCC(ret) && i < candidates_.candidate_plans_.count(); i++) {
|
||||
candidate_plan = candidates_.candidate_plans_.at(i);
|
||||
OPT_TRACE("generate merge distinct for plan:", candidate_plan);
|
||||
if (OB_FAIL(create_merge_distinct_plan(candidate_plan.plan_tree_,
|
||||
distinct_helper,
|
||||
reduce_exprs,
|
||||
distinct_exprs,
|
||||
can_ignore_merge_plan))) {
|
||||
LOG_WARN("failed to allocate merge distinct plan", K(ret));
|
||||
} else if (NULL != candidate_plan.plan_tree_
|
||||
&& OB_FAIL(distinct_plans.push_back(candidate_plan))) {
|
||||
LOG_WARN("failed to add merge distinct candidate plan", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSelectLogPlan::get_distinct_exprs(const ObLogicalOperator *top,
|
||||
ObIArray<ObRawExpr *> &reduce_exprs,
|
||||
ObIArray<ObRawExpr *> &distinct_exprs)
|
||||
@ -1561,9 +1591,9 @@ int ObSelectLogPlan::get_distinct_exprs(const ObLogicalOperator *top,
|
||||
}
|
||||
|
||||
int ObSelectLogPlan::create_hash_distinct_plan(ObLogicalOperator *&top,
|
||||
GroupingOpHelper &distinct_helper,
|
||||
ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
ObIArray<ObRawExpr*> &distinct_exprs)
|
||||
const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &distinct_exprs)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_partition_wise = false;
|
||||
@ -1571,14 +1601,14 @@ int ObSelectLogPlan::create_hash_distinct_plan(ObLogicalOperator *&top,
|
||||
if (OB_ISNULL(top)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(top), K(ret));
|
||||
} else if (top->is_distributed() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
} else if (!top->is_distributed() && !distinct_helper.allow_basic()) {
|
||||
top = NULL;
|
||||
OPT_TRACE("ignore basic distinct by hint");
|
||||
} else if (top->is_distributed() && distinct_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check sharding compatible with reduce expr", K(ret));
|
||||
} else if (!top->is_distributed() ||
|
||||
(is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!top->is_distributed() || is_partition_wise) {
|
||||
OPT_TRACE("is basic distinct:", !top->is_distributed());
|
||||
OPT_TRACE("is partition wise distinct", is_partition_wise);
|
||||
if (OB_FAIL(allocate_distinct_as_top(top,
|
||||
@ -1613,11 +1643,9 @@ int ObSelectLogPlan::create_hash_distinct_plan(ObLogicalOperator *&top,
|
||||
}
|
||||
|
||||
int ObSelectLogPlan::create_merge_distinct_plan(ObLogicalOperator *&top,
|
||||
GroupingOpHelper &distinct_helper,
|
||||
ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
ObIArray<ObOrderDirection> &directions,
|
||||
bool &is_plan_valid,
|
||||
const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &in_distinct_exprs,
|
||||
bool can_ignore_merge_plan)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1626,11 +1654,19 @@ int ObSelectLogPlan::create_merge_distinct_plan(ObLogicalOperator *&top,
|
||||
bool is_partition_wise = false;
|
||||
ObSEArray<OrderItem, 4> sort_keys;
|
||||
int64_t interesting_order_info = OrderingFlag::NOT_MATCH;
|
||||
is_plan_valid = true;
|
||||
ObSEArray<ObRawExpr*, 4> distinct_exprs;
|
||||
ObSEArray<ObOrderDirection, 4> directions;
|
||||
OPT_TRACE("start generate merge distinct plan");
|
||||
if (OB_ISNULL(top)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (!top->is_distributed() && !distinct_helper.allow_basic()) {
|
||||
top = NULL;
|
||||
OPT_TRACE("ignore basic distinct by hint");
|
||||
} else if (OB_FAIL(distinct_exprs.assign(in_distinct_exprs))) {
|
||||
LOG_WARN("failed to assign distinct exprs", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::get_default_directions(distinct_exprs.count(), directions))) {
|
||||
LOG_WARN("failed to generate default directions", K(ret));
|
||||
} else if (OB_FAIL(adjust_sort_expr_ordering(distinct_exprs,
|
||||
directions,
|
||||
*top,
|
||||
@ -1660,15 +1696,12 @@ int ObSelectLogPlan::create_merge_distinct_plan(ObLogicalOperator *&top,
|
||||
LOG_WARN("failed to compute stmt interesting order", K(ret));
|
||||
} else if (need_sort && can_ignore_merge_plan && OrderingFlag::NOT_MATCH == interesting_order_info) {
|
||||
// if no further order needed, not generate merge style distinct
|
||||
is_plan_valid = false;
|
||||
} else if (top->is_distributed() &&
|
||||
OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
top = NULL;
|
||||
} else if (top->is_distributed() && distinct_helper.allow_partition_wise(top->is_parallel_more_than_part_cnt())
|
||||
&& OB_FAIL(top->check_sharding_compatible_with_reduce_expr(reduce_exprs,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check sharding compatible with reduce exprs", K(ret));
|
||||
} else if (!top->is_distributed() ||
|
||||
(is_partition_wise &&
|
||||
!(top->is_parallel_more_than_part_cnt() &&
|
||||
get_optimizer_context().get_query_ctx()->optimizer_features_enable_version_ > COMPAT_VERSION_4_3_2))) {
|
||||
} else if (!top->is_distributed() || is_partition_wise) {
|
||||
OPT_TRACE("is basic distinct:", !top->is_distributed());
|
||||
OPT_TRACE("is partition wise distinct", is_partition_wise);
|
||||
if (OB_FAIL(try_allocate_sort_as_top(top, sort_keys, need_sort, prefix_pos))) {
|
||||
|
@ -83,7 +83,6 @@ private:
|
||||
|
||||
int get_valid_aggr_algo(const ObIArray<ObRawExpr*> &group_by_exprs,
|
||||
const GroupingOpHelper &groupby_helper,
|
||||
const bool ignore_hint,
|
||||
bool &use_hash_valid,
|
||||
bool &use_merge_valid,
|
||||
bool &part_sort_valid,
|
||||
@ -96,9 +95,7 @@ private:
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
const bool ignore_hint,
|
||||
ObIArray<CandidatePlan> &groupby_plans);
|
||||
|
||||
int candi_allocate_three_stage_group_by(const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
@ -108,7 +105,6 @@ private:
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObIArray<CandidatePlan> &groupby_plans);
|
||||
|
||||
@ -117,7 +113,6 @@ private:
|
||||
const ObIArray<ObRawExpr*> &rollup_exprs,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top);
|
||||
|
||||
@ -159,7 +154,6 @@ private:
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
CandidatePlan &candidate_plan,
|
||||
ObIArray<CandidatePlan> &candidate_plans,
|
||||
@ -186,17 +180,20 @@ private:
|
||||
common::ObIArray <ObRawExpr *> &reduce_exprs,
|
||||
common::ObIArray <ObRawExpr *> &distinct_exprs);
|
||||
|
||||
int inner_candi_allocate_distinct(const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
ObIArray<CandidatePlan> &distinct_plans);
|
||||
|
||||
int create_hash_distinct_plan(ObLogicalOperator *&top,
|
||||
GroupingOpHelper &distinct_helper,
|
||||
ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
ObIArray<ObRawExpr*> &distinct_exprs);
|
||||
const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &distinct_exprs);
|
||||
|
||||
int create_merge_distinct_plan(ObLogicalOperator *&top,
|
||||
GroupingOpHelper &distinct_helper,
|
||||
ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
ObIArray<ObOrderDirection> &directions,
|
||||
bool &is_plan_valid,
|
||||
const GroupingOpHelper &distinct_helper,
|
||||
const ObIArray<ObRawExpr*> &reduce_exprs,
|
||||
const ObIArray<ObRawExpr*> &distinct_exprs,
|
||||
bool can_ignore_merge_plan = false);
|
||||
|
||||
int allocate_distinct_as_top(ObLogicalOperator *&top,
|
||||
@ -924,7 +921,6 @@ int generate_window_functions_plan(WinFuncOpHelper &win_func_helper,
|
||||
const ObIArray<ObOrderDirection> &rollup_directions,
|
||||
const ObIArray<ObAggFunRawExpr*> &aggr_items,
|
||||
const ObIArray<ObRawExpr*> &having_exprs,
|
||||
const bool is_from_povit,
|
||||
GroupingOpHelper &groupby_helper,
|
||||
ObLogicalOperator *&top,
|
||||
bool use_part_sort,
|
||||
|
@ -1086,6 +1086,7 @@ Timestamp{whitespace}?\"[^\"]*\" {
|
||||
<hint>BC2HOST { return BC2HOST; }
|
||||
<hint>RANGE { return RANGE; }
|
||||
<hint>LIST { return LIST; }
|
||||
<hint>BASIC { return BASIC; }
|
||||
<hint>[-] { return NEG_SIGN; }
|
||||
<hint>MERGE { return MERGE_HINT; }
|
||||
<hint>NO_MERGE { return NO_MERGE_HINT; }
|
||||
@ -1171,6 +1172,8 @@ Timestamp{whitespace}?\"[^\"]*\" {
|
||||
<hint>PUSHDOWN { return PUSHDOWN; }
|
||||
<hint>DECORRELATE { return DECORRELATE; }
|
||||
<hint>NO_DECORRELATE { return NO_DECORRELATE; }
|
||||
<hint>PQ_GBY { return PQ_GBY; }
|
||||
<hint>PQ_DISTINCT { return PQ_DISTINCT; }
|
||||
<hint>{identifier} {
|
||||
if (!(IS_FAST_PARAMETERIZE)) {
|
||||
check_value(yylval);
|
||||
|
@ -190,7 +190,7 @@ USE_HASH_AGGREGATION NO_USE_HASH_AGGREGATION
|
||||
PARTITION_SORT NO_PARTITION_SORT WF_TOPN
|
||||
USE_LATE_MATERIALIZATION NO_USE_LATE_MATERIALIZATION
|
||||
PX_JOIN_FILTER NO_PX_JOIN_FILTER PX_PART_JOIN_FILTER NO_PX_PART_JOIN_FILTER
|
||||
PQ_MAP PQ_DISTRIBUTE PQ_DISTRIBUTE_WINDOW PQ_SET PQ_SUBQUERY RANDOM_LOCAL BROADCAST BC2HOST LIST
|
||||
PQ_MAP PQ_DISTRIBUTE PQ_DISTRIBUTE_WINDOW PQ_SET PQ_SUBQUERY PQ_GBY PQ_DISTINCT RANDOM_LOCAL BROADCAST BC2HOST LIST
|
||||
GBY_PUSHDOWN NO_GBY_PUSHDOWN
|
||||
USE_HASH_DISTINCT NO_USE_HASH_DISTINCT
|
||||
DISTINCT_PUSHDOWN NO_DISTINCT_PUSHDOWN
|
||||
@ -11285,6 +11285,14 @@ INDEX_HINT '(' qb_name_option relation_factor_in_hint NAME_OB opt_index_prefix '
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_NO_USE_COLUMN_STORE_HINT, 2, $3, $4);
|
||||
}
|
||||
| PQ_GBY '(' qb_name_option distribute_method ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_PQ_GBY_HINT, 2, $3, $4);
|
||||
}
|
||||
| PQ_DISTINCT '(' qb_name_option distribute_method ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_PQ_DISTINCT_HINT, 2, $3, $4);
|
||||
}
|
||||
;
|
||||
|
||||
opt_index_prefix:
|
||||
@ -11531,6 +11539,10 @@ ALL
|
||||
{
|
||||
malloc_terminal_node($$, result->malloc_pool_, T_DISTRIBUTE_LIST);
|
||||
}
|
||||
| BASIC
|
||||
{
|
||||
malloc_terminal_node($$, result->malloc_pool_, T_DISTRIBUTE_BASIC);
|
||||
}
|
||||
;
|
||||
|
||||
limit_expr:
|
||||
|
@ -14617,6 +14617,13 @@ int ObDMLResolver::resolve_optimize_hint(const ParseNode &hint_node,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_PQ_GBY_HINT:
|
||||
case T_PQ_DISTINCT_HINT: {
|
||||
if (OB_FAIL(resolve_normal_pq_hint(hint_node, opt_hint))) {
|
||||
LOG_WARN("failed to resolve normal pq hint.", K(ret));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_USE_LATE_MATERIALIZATION:
|
||||
case T_NO_USE_LATE_MATERIALIZATION:
|
||||
case T_GBY_PUSHDOWN:
|
||||
@ -15098,6 +15105,34 @@ int ObDMLResolver::resolve_pq_subquery_hint(const ParseNode &hint_node,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::resolve_normal_pq_hint(const ParseNode &hint_node,
|
||||
ObOptHint *&opt_hint)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
opt_hint = NULL;
|
||||
const ParseNode *dist_method_node = NULL;
|
||||
ObPQHint *pq_hint = NULL;
|
||||
ObString qb_name;
|
||||
if (OB_UNLIKELY(T_PQ_GBY_HINT != hint_node.type_ && T_PQ_DISTINCT_HINT != hint_node.type_)
|
||||
|| OB_UNLIKELY(2 != hint_node.num_child_)
|
||||
|| OB_ISNULL(dist_method_node = hint_node.children_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected pq_gby/pq_distinct hint node", K(ret), K(hint_node.num_child_),
|
||||
K(get_type_name(hint_node.type_)));
|
||||
} else if (NULL == ObPQHint::get_dist_method_str(dist_method_node->type_)) {
|
||||
LOG_TRACE("invalid normal pq hint dist_method_node", K(get_type_name(dist_method_node->type_)));
|
||||
} else if (OB_FAIL(ObQueryHint::create_hint(allocator_, hint_node.type_, pq_hint))) {
|
||||
LOG_WARN("failed to create hint", K(ret));
|
||||
} else if (OB_FAIL(resolve_qb_name_node(hint_node.children_[0], qb_name))) {
|
||||
LOG_WARN("failed to resolve query block name", K(ret));
|
||||
} else {
|
||||
pq_hint->set_qb_name(qb_name);
|
||||
pq_hint->set_dist_method(dist_method_node->type_);
|
||||
opt_hint = pq_hint;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::resolve_join_filter_hint(const ParseNode &hint_node,
|
||||
ObOptHint *&opt_hint)
|
||||
{
|
||||
|
@ -946,6 +946,7 @@ private:
|
||||
int resolve_pq_distribute_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_pq_set_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_pq_subquery_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_normal_pq_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_join_filter_hint(const ParseNode &join_node, ObOptHint *&opt_hint);
|
||||
int resolve_aggregation_hint(const ParseNode &hint_node, ObOptHint *&hint);
|
||||
int resolve_normal_transform_hint(const ParseNode &hint_node, ObTransHint *&hint);
|
||||
|
@ -1160,6 +1160,8 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul
|
||||
case T_USE_DISTRIBUTED_DML: return is_enable_hint ? "USE_DISTRIBUTED_DML" : "NO_USE_DISTRIBUTED_DML";
|
||||
case T_TABLE_DYNAMIC_SAMPLING: return "DYNAMIC_SAMPLING";
|
||||
case T_PQ_SUBQUERY: return "PQ_SUBQUERY";
|
||||
case T_PQ_GBY_HINT: return "PQ_GBY";
|
||||
case T_PQ_DISTINCT_HINT: return "PQ_DISTINCT";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -2527,6 +2529,43 @@ int ObPQSubqueryHint::print_hint_desc(PlanText &plan_text) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPQHint::assign(const ObPQHint &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
dist_method_ = other.dist_method_;
|
||||
if (OB_FAIL(ObOptHint::assign(other))) {
|
||||
LOG_WARN("fail to assign hint", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPQHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
const char *str = NULL;
|
||||
if (OB_ISNULL(str = ObPQHint::get_dist_method_str(dist_method_))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(dist_method_));
|
||||
} else if (OB_FAIL(BUF_PRINTF(" %s", str))) {
|
||||
LOG_WARN("failed to print dist method", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *ObPQHint::get_dist_method_str(ObItemType dist_method)
|
||||
{
|
||||
switch (dist_method) {
|
||||
case T_DISTRIBUTE_BASIC: return "BASIC";
|
||||
case T_DISTRIBUTE_NONE: return "NONE";
|
||||
case T_DISTRIBUTE_HASH: return "HASH";
|
||||
default: return NULL;
|
||||
}
|
||||
return NULL;
|
||||
};
|
||||
|
||||
int ObJoinOrderHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
@ -525,7 +525,8 @@ public:
|
||||
HINT_TABLE_PARALLEL,
|
||||
HINT_PQ_SET,
|
||||
HINT_JOIN_FILTER,
|
||||
HINT_TABLE_DYNAMIC_SAMPLING
|
||||
HINT_TABLE_DYNAMIC_SAMPLING,
|
||||
HINT_PQ
|
||||
};
|
||||
|
||||
static const int64_t MAX_EXPR_STR_LENGTH_IN_HINT = 1024;
|
||||
@ -992,7 +993,7 @@ public:
|
||||
const ObTableInHint &get_table() const { return table_; }
|
||||
int64_t get_parallel() const { return parallel_; }
|
||||
void set_parallel(int64_t parallel) { parallel_ = parallel; }
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table), K_(table), K_(parallel));
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table), K_(parallel));
|
||||
|
||||
private:
|
||||
ObTableInHint table_;
|
||||
@ -1114,6 +1115,31 @@ private:
|
||||
QbNameList sub_qb_names_;
|
||||
};
|
||||
|
||||
// normal pq hint for single child op: group by/distinct
|
||||
class ObPQHint : public ObOptHint
|
||||
{
|
||||
public:
|
||||
ObPQHint(ObItemType hint_type)
|
||||
: ObOptHint(hint_type),
|
||||
dist_method_(T_INVALID)
|
||||
{
|
||||
set_hint_class(HINT_PQ);
|
||||
}
|
||||
int assign(const ObPQHint &other);
|
||||
virtual ~ObPQHint() {}
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
static const char* get_dist_method_str(ObItemType dist_method);
|
||||
void set_dist_method(ObItemType dist_method) { dist_method_ = dist_method; }
|
||||
inline bool is_dist_method_match(ObItemType dist_method) const { return dist_method_ == dist_method; }
|
||||
inline bool is_force_basic() const { return T_DISTRIBUTE_BASIC == dist_method_; }
|
||||
inline bool is_force_partition_wise() const { return T_DISTRIBUTE_NONE == dist_method_; }
|
||||
inline bool is_force_dist_hash() const { return T_DISTRIBUTE_HASH == dist_method_; }
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(dist_method));
|
||||
private:
|
||||
ObItemType dist_method_;
|
||||
};
|
||||
|
||||
class ObJoinOrderHint : public ObOptHint {
|
||||
public:
|
||||
ObJoinOrderHint(ObItemType hint_type = T_LEADING)
|
||||
|
@ -1405,7 +1405,7 @@ void ObLogPlanHint::reset()
|
||||
table_hints_.reuse();
|
||||
join_hints_.reuse();
|
||||
normal_hints_.reuse();
|
||||
enable_index_prefix_ = false;
|
||||
optimizer_features_enable_version_ = LASTED_COMPAT_VERSION;
|
||||
}
|
||||
|
||||
#ifndef OB_BUILD_SPM
|
||||
@ -1425,7 +1425,7 @@ int ObLogPlanHint::init_log_plan_hint(ObSqlSchemaGuard &schema_guard,
|
||||
#ifdef OB_BUILD_SPM
|
||||
is_spm_evolution_ = is_spm_evolution;
|
||||
#endif
|
||||
enable_index_prefix_ = (stmt.get_query_ctx()->optimizer_features_enable_version_ >= COMPAT_VERSION_4_2_3);
|
||||
optimizer_features_enable_version_ = stmt.get_query_ctx()->optimizer_features_enable_version_;
|
||||
const ObStmtHint &stmt_hint = stmt.get_stmt_hint();
|
||||
if (OB_FAIL(join_order_.init_leading_info(stmt, query_hint, stmt_hint.get_normal_hint(T_LEADING)))) {
|
||||
LOG_WARN("failed to get leading hint info", K(ret));
|
||||
@ -1721,14 +1721,23 @@ bool ObLogPlanHint::has_disable_hint(ObItemType hint_type) const
|
||||
int ObLogPlanHint::get_aggregation_info(bool &force_use_hash,
|
||||
bool &force_use_merge,
|
||||
bool &force_part_sort,
|
||||
bool &force_normal_sort) const
|
||||
bool &force_normal_sort,
|
||||
bool &force_basic,
|
||||
bool &force_partition_wise,
|
||||
bool &force_dist_hash) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
force_use_hash = false;
|
||||
force_use_merge = false;
|
||||
force_part_sort = false;
|
||||
force_normal_sort = false;
|
||||
force_basic = false;
|
||||
force_partition_wise = false;
|
||||
force_dist_hash = false;
|
||||
const ObAggHint *agg_hint = static_cast<const ObAggHint*>(get_normal_hint(T_USE_HASH_AGGREGATE));
|
||||
const ObPQHint *pq_hint = static_cast<const ObPQHint*>(get_normal_hint(T_PQ_GBY_HINT));
|
||||
const bool enable_pq_hint = COMPAT_VERSION_4_3_3 <= optimizer_features_enable_version_
|
||||
|| COMPAT_VERSION_4_2_4 < optimizer_features_enable_version_;
|
||||
if (NULL != agg_hint) {
|
||||
force_use_hash = agg_hint->is_enable_hint();
|
||||
force_use_merge = agg_hint->is_disable_hint();
|
||||
@ -1741,6 +1750,51 @@ int ObLogPlanHint::get_aggregation_info(bool &force_use_hash,
|
||||
force_use_merge = true;
|
||||
force_normal_sort = true;
|
||||
}
|
||||
if (OB_FAIL(ret) || !enable_pq_hint) {
|
||||
} else if (NULL != pq_hint) {
|
||||
force_basic = pq_hint->is_force_basic();
|
||||
force_partition_wise = pq_hint->is_force_partition_wise();
|
||||
force_dist_hash = pq_hint->is_force_dist_hash();
|
||||
} else if (is_outline_data_) {
|
||||
force_basic = true;
|
||||
force_partition_wise = false;
|
||||
force_dist_hash = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlanHint::get_distinct_info(bool &force_use_hash,
|
||||
bool &force_use_merge,
|
||||
bool &force_basic,
|
||||
bool &force_partition_wise,
|
||||
bool &force_dist_hash) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
force_use_hash = false;
|
||||
force_use_merge = false;
|
||||
force_basic = false;
|
||||
force_partition_wise = false;
|
||||
force_dist_hash = false;
|
||||
const ObHint *method_hint = static_cast<const ObAggHint*>(get_normal_hint(T_USE_HASH_DISTINCT));
|
||||
const ObPQHint *pq_hint = static_cast<const ObPQHint*>(get_normal_hint(T_PQ_DISTINCT_HINT));
|
||||
const bool enable_pq_hint = COMPAT_VERSION_4_3_3 <= optimizer_features_enable_version_
|
||||
|| COMPAT_VERSION_4_2_4 < optimizer_features_enable_version_;
|
||||
if (NULL != method_hint) {
|
||||
force_use_hash = method_hint->is_enable_hint();
|
||||
force_use_merge = method_hint->is_disable_hint();
|
||||
} else if (is_outline_data_) {
|
||||
force_use_merge = true;
|
||||
}
|
||||
if (OB_FAIL(ret) || !enable_pq_hint) {
|
||||
} else if (NULL != pq_hint) {
|
||||
force_basic = pq_hint->is_force_basic();
|
||||
force_partition_wise = pq_hint->is_force_partition_wise();
|
||||
force_dist_hash = pq_hint->is_force_dist_hash();
|
||||
} else if (is_outline_data_) {
|
||||
force_basic = true;
|
||||
force_partition_wise = false;
|
||||
force_dist_hash = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1941,7 +1995,8 @@ int ObLogPlanHint::get_index_prefix(const uint64_t table_id,
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const LogTableHint *log_table_hint = NULL;
|
||||
if (!enable_index_prefix_ || OB_ISNULL(log_table_hint = get_index_hint(table_id))) {
|
||||
if (optimizer_features_enable_version_ < COMPAT_VERSION_4_2_3
|
||||
|| OB_ISNULL(log_table_hint = get_index_hint(table_id))) {
|
||||
//do nothing
|
||||
} else if (!log_table_hint->is_use_index_hint()) {
|
||||
//do nothing
|
||||
|
@ -470,7 +470,15 @@ struct ObLogPlanHint
|
||||
int get_aggregation_info(bool &force_use_hash,
|
||||
bool &force_use_merge,
|
||||
bool &force_part_sort,
|
||||
bool &force_normal_sort) const;
|
||||
bool &force_normal_sort,
|
||||
bool &force_basic,
|
||||
bool &force_partition_wise,
|
||||
bool &force_dist_hash) const;
|
||||
int get_distinct_info(bool &force_use_hash,
|
||||
bool &force_use_merge,
|
||||
bool &force_basic,
|
||||
bool &force_partition_wise,
|
||||
bool &force_dist_hash) const;
|
||||
int get_valid_pq_subquery_hint(const ObIArray<ObString> &sub_qb_names,
|
||||
const ObPQSubqueryHint *&explicit_hint,
|
||||
const ObPQSubqueryHint *&implicit_hint) const;
|
||||
@ -482,12 +490,8 @@ struct ObLogPlanHint
|
||||
|
||||
bool use_late_material() const { return has_enable_hint(T_USE_LATE_MATERIALIZATION); }
|
||||
bool no_use_late_material() const { return has_disable_hint(T_USE_LATE_MATERIALIZATION); }
|
||||
bool use_hash_aggregate() const { return has_enable_hint(T_USE_HASH_AGGREGATE); }
|
||||
bool use_merge_aggregate() const { return has_disable_hint(T_USE_HASH_AGGREGATE); }
|
||||
bool pushdown_group_by() const { return has_enable_hint(T_GBY_PUSHDOWN); }
|
||||
bool no_pushdown_group_by() const { return has_disable_hint(T_GBY_PUSHDOWN); }
|
||||
bool use_hash_distinct() const { return has_enable_hint(T_USE_HASH_DISTINCT); }
|
||||
bool use_merge_distinct() const { return has_disable_hint(T_USE_HASH_DISTINCT); }
|
||||
bool pushdown_distinct() const { return has_enable_hint(T_DISTINCT_PUSHDOWN); }
|
||||
bool no_pushdown_distinct() const { return has_disable_hint(T_DISTINCT_PUSHDOWN); }
|
||||
bool use_distributed_dml() const { return has_enable_hint(T_USE_DISTRIBUTED_DML); }
|
||||
@ -497,7 +501,7 @@ struct ObLogPlanHint
|
||||
|
||||
TO_STRING_KV(K_(is_outline_data), K_(join_order),
|
||||
K_(table_hints), K_(join_hints),
|
||||
K_(normal_hints), K_(enable_index_prefix));
|
||||
K_(normal_hints), K_(optimizer_features_enable_version));
|
||||
|
||||
bool is_outline_data_;
|
||||
#ifdef OB_BUILD_SPM
|
||||
@ -507,7 +511,7 @@ struct ObLogPlanHint
|
||||
common::ObSEArray<LogTableHint, 4, common::ModulePageAllocator, true> table_hints_;
|
||||
common::ObSEArray<LogJoinHint, 8, common::ModulePageAllocator, true> join_hints_;
|
||||
common::ObSEArray<const ObHint*, 8, common::ModulePageAllocator, true> normal_hints_;
|
||||
bool enable_index_prefix_;
|
||||
uint64_t optimizer_features_enable_version_;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user