Add hint index_asc/index_desc and Adjust scan direction at the end of the plan generation
This commit is contained in:
parent
1db265ae09
commit
2e64e7adcb
@ -2690,6 +2690,10 @@ typedef enum ObItemType
|
||||
T_CREATE_WRAPPED_FUNCTION = 4769,
|
||||
T_CREATE_WRAPPED_PROCEDURE = 4770,
|
||||
T_BASE64_CIPHER = 4771,
|
||||
|
||||
// optimizer hint
|
||||
T_INDEX_ASC_HINT = 4772,
|
||||
T_INDEX_DESC_HINT = 4773,
|
||||
T_MAX //Attention: add a new type before T_MAX
|
||||
} ObItemType;
|
||||
|
||||
|
@ -157,6 +157,7 @@ public:
|
||||
is_fulltext_index_(false),
|
||||
is_multivalue_index_(false),
|
||||
is_vector_index_(false),
|
||||
force_direction_(false),
|
||||
range_info_(),
|
||||
ordering_info_(),
|
||||
interesting_order_info_(OrderingFlag::NOT_MATCH),
|
||||
@ -200,6 +201,8 @@ public:
|
||||
ObShardingInfo *get_sharding_info() const { return sharding_info_; }
|
||||
bool is_multivalue_index() const { return is_multivalue_index_; }
|
||||
void set_is_multivalue_index(const bool is_multivalue_index) { is_multivalue_index_ = is_multivalue_index; }
|
||||
bool is_force_direction() const { return force_direction_; }
|
||||
void set_force_direction(bool force) { force_direction_ = force; }
|
||||
TO_STRING_KV(K_(index_id), K_(is_unique_index), K_(is_index_back), K_(is_index_global),
|
||||
K_(is_fulltext_index), K_(is_multivalue_index), K_(range_info), K_(ordering_info), K_(interesting_order_info),
|
||||
K_(interesting_order_prefix_count));
|
||||
@ -212,6 +215,7 @@ private:
|
||||
bool is_fulltext_index_;
|
||||
bool is_multivalue_index_;
|
||||
bool is_vector_index_;
|
||||
bool force_direction_;
|
||||
QueryRangeInfo range_info_;
|
||||
OrderingInfo ordering_info_;
|
||||
int64_t interesting_order_info_; // 记录索引的序在stmt中的哪些地方用到 e.g. join, group by, order by
|
||||
|
@ -1776,6 +1776,7 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id,
|
||||
ap->index_prefix_ = index_info_entry->get_range_info().get_index_prefix();
|
||||
ap->use_column_store_ = use_column_store;
|
||||
ap->est_cost_info_.use_column_store_ = use_column_store;
|
||||
ap->force_direction_ = index_info_entry->is_force_direction();
|
||||
|
||||
ap->contain_das_op_ = ap->use_das_;
|
||||
ap->is_ror_ = (ref_id == index_id) ? true
|
||||
@ -2153,6 +2154,7 @@ int ObJoinOrder::get_access_path_ordering(const uint64_t table_id,
|
||||
common::ObIArray<ObRawExpr*> &index_keys,
|
||||
common::ObIArray<ObRawExpr*> &ordering,
|
||||
ObOrderDirection &direction,
|
||||
bool &force_direction,
|
||||
const bool is_index_back)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -2161,10 +2163,13 @@ int ObJoinOrder::get_access_path_ordering(const uint64_t table_id,
|
||||
ObOptimizerContext *opt_ctx = NULL;
|
||||
ObSqlSchemaGuard *schema_guard = NULL;
|
||||
const ObTableSchema *index_schema = NULL;
|
||||
ObOrderDirection hint_direction = UNORDERED;
|
||||
force_direction = false;
|
||||
if (OB_ISNULL(get_plan())
|
||||
|| OB_ISNULL(stmt = get_plan()->get_stmt())
|
||||
|| OB_ISNULL(opt_ctx = &get_plan()->get_optimizer_context())
|
||||
|| OB_ISNULL(schema_guard = opt_ctx->get_sql_schema_guard())) {
|
||||
|| OB_ISNULL(schema_guard = opt_ctx->get_sql_schema_guard())
|
||||
|| OB_ISNULL(opt_ctx->get_query_ctx())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("NULL pointer error",
|
||||
K(get_plan()), K(stmt), K(opt_ctx), K(schema_guard), K(ret));
|
||||
@ -2181,6 +2186,14 @@ int ObJoinOrder::get_access_path_ordering(const uint64_t table_id,
|
||||
// for global index lookup without keep order, the ordering is wrong.
|
||||
} else if (OB_FAIL(append(ordering, index_keys))) {
|
||||
LOG_WARN("failed to append index ordering expr", K(ret));
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().check_scan_direction(*opt_ctx->get_query_ctx(),
|
||||
table_id,
|
||||
index_id,
|
||||
hint_direction))) {
|
||||
LOG_WARN("failed to check scan direction", K(ret), K(table_id));
|
||||
} else if (UNORDERED != hint_direction) {
|
||||
direction = hint_direction;
|
||||
force_direction = true;
|
||||
} else if (OB_FAIL(get_index_scan_direction(ordering, stmt,
|
||||
get_plan()->get_equal_sets(), direction))) {
|
||||
LOG_WARN("failed to get index scan direction", K(ret));
|
||||
@ -2639,6 +2652,7 @@ int ObJoinOrder::fill_index_info_entry(const uint64_t table_id,
|
||||
entry->set_index_id(index_id);
|
||||
int64_t interesting_order_info = OrderingFlag::NOT_MATCH;
|
||||
int64_t max_prefix_count = 0;
|
||||
bool force_direction = false;
|
||||
if (OB_FAIL(get_simple_index_info(table_id, base_table_id, index_id,
|
||||
is_unique_index, is_index_back, is_index_global))) {
|
||||
LOG_WARN("failed to get simple index info", K(ret));
|
||||
@ -2646,6 +2660,7 @@ int ObJoinOrder::fill_index_info_entry(const uint64_t table_id,
|
||||
entry->get_ordering_info().get_index_keys(),
|
||||
entry->get_ordering_info().get_ordering(),
|
||||
direction,
|
||||
force_direction,
|
||||
is_index_back))) {
|
||||
LOG_WARN("get access path ordering ", K(ret));
|
||||
} else {
|
||||
@ -2657,6 +2672,7 @@ int ObJoinOrder::fill_index_info_entry(const uint64_t table_id,
|
||||
entry->set_is_multivalue_index(index_schema->is_multivalue_index_aux());
|
||||
entry->set_is_vector_index(index_schema->is_vec_index());
|
||||
entry->get_ordering_info().set_scan_direction(direction);
|
||||
entry->set_force_direction(force_direction);
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObSEArray<OrderItem, 4> index_ordering;
|
||||
@ -6194,6 +6210,7 @@ int AccessPath::assign(const AccessPath &other, common::ObIAllocator *allocator)
|
||||
table_partition_info_ = other.table_partition_info_;
|
||||
is_get_ = other.is_get_;
|
||||
order_direction_ = other.order_direction_;
|
||||
force_direction_ = other.force_direction_;
|
||||
is_hash_index_ = other.is_hash_index_;
|
||||
sample_info_ = other.sample_info_;
|
||||
range_prefix_count_ = other.range_prefix_count_;
|
||||
|
@ -573,6 +573,7 @@ struct TRIndexAccessInfo
|
||||
pre_range_graph_(NULL),
|
||||
is_get_(false),
|
||||
order_direction_(direction),
|
||||
force_direction_(false),
|
||||
is_hash_index_(false),
|
||||
est_cost_info_(table_id,
|
||||
ref_table_id,
|
||||
@ -727,6 +728,7 @@ struct TRIndexAccessInfo
|
||||
ObPreRangeGraph* pre_range_graph_; // pre_query_graph for each access path
|
||||
bool is_get_;
|
||||
ObOrderDirection order_direction_;//序的方向(升序or倒序)
|
||||
bool force_direction_;
|
||||
bool is_hash_index_; // is hash index (virtual table and is index)
|
||||
ObCostTableScanInfo est_cost_info_; // estimate cost info
|
||||
common::ObSEArray<ObEstRowCountRecord, 2,
|
||||
@ -1846,6 +1848,7 @@ struct NullAwareAntiJoinInfo {
|
||||
common::ObIArray<ObRawExpr *> &index_keys,
|
||||
common::ObIArray<ObRawExpr *> &ordering,
|
||||
ObOrderDirection &direction,
|
||||
bool &force_direction,
|
||||
const bool is_index_back);
|
||||
|
||||
int get_index_scan_direction(const ObIArray<ObRawExpr *> &keys,
|
||||
|
@ -9468,6 +9468,9 @@ int ObLogPlan::plan_tree_traverse(const TraverseOp &operation, void *ctx)
|
||||
case ALLOC_STARTUP_EXPR:
|
||||
default:
|
||||
break;
|
||||
case ADJUST_SCAN_DIRECTION: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (((PX_ESTIMATE_SIZE == operation) ||
|
||||
@ -10929,7 +10932,8 @@ int ObLogPlan::generate_plan()
|
||||
GEN_LOCATION_CONSTRAINT,
|
||||
PX_ESTIMATE_SIZE,
|
||||
ALLOC_STARTUP_EXPR,
|
||||
COLLECT_BATCH_EXEC_PARAM))) {
|
||||
COLLECT_BATCH_EXEC_PARAM,
|
||||
ADJUST_SCAN_DIRECTION))) {
|
||||
LOG_WARN("failed to do plan traverse", K(ret));
|
||||
} else if (OB_FAIL(do_post_traverse_processing())) {
|
||||
LOG_WARN("failed to post traverse processing", K(ret));
|
||||
|
@ -670,7 +670,7 @@ int ObLogSort::try_allocate_pushdown_topn_runtime_filter()
|
||||
LOG_WARN("fail to generate p2p dh id", K(ret));
|
||||
} else {
|
||||
(void)topn_filter_info_.init(p2p_sequence_id, pushdown_topn_filter_expr, effective_sk_cnt,
|
||||
tsc_has_exchange);
|
||||
tsc_has_exchange, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,16 +27,17 @@ struct ObTopNFilterInfo
|
||||
public:
|
||||
ObTopNFilterInfo()
|
||||
: enabled_(false), p2p_sequence_id_(OB_INVALID_ID), pushdown_topn_filter_expr_(nullptr),
|
||||
effective_sk_cnt_(0), is_shuffle_(false)
|
||||
effective_sk_cnt_(0), is_shuffle_(false), topn_filter_node_(NULL)
|
||||
{}
|
||||
inline void init(int64_t p2p_sequence_id, ObRawExpr *pushdown_topn_filter_expr,
|
||||
int64_t effective_sk_cnt, bool is_shuffle)
|
||||
int64_t effective_sk_cnt, bool is_shuffle, ObLogicalOperator* node)
|
||||
{
|
||||
p2p_sequence_id_ = p2p_sequence_id;
|
||||
pushdown_topn_filter_expr_ = pushdown_topn_filter_expr;
|
||||
effective_sk_cnt_ = effective_sk_cnt;
|
||||
is_shuffle_ = is_shuffle;
|
||||
enabled_ = true;
|
||||
topn_filter_node_ = node;
|
||||
}
|
||||
TO_STRING_KV(K_(enabled), K_(p2p_sequence_id), KP_(pushdown_topn_filter_expr),
|
||||
K_(effective_sk_cnt), K_(is_shuffle));
|
||||
@ -49,6 +50,7 @@ public:
|
||||
int64_t effective_sk_cnt_;
|
||||
// the topn sort op and the tsc op not in same dfo, need shuffle
|
||||
bool is_shuffle_;
|
||||
ObLogicalOperator *topn_filter_node_;
|
||||
};
|
||||
|
||||
class ObLogSort : public ObLogicalOperator
|
||||
@ -145,6 +147,7 @@ public:
|
||||
inline bool is_shuffle_pd_topn_filter() { return topn_filter_info_.is_shuffle_; }
|
||||
int try_allocate_pushdown_topn_runtime_filter();
|
||||
int check_use_child_ordering(bool &used, int64_t &inherit_child_ordering_index);
|
||||
ObLogicalOperator *get_topn_filter_node() const { return topn_filter_info_.topn_filter_node_; }
|
||||
protected:
|
||||
virtual int inner_replace_op_exprs(ObRawExprReplacer &replacer);
|
||||
int est_sort_key_width();
|
||||
|
@ -2331,7 +2331,9 @@ int ObLogTableScan::print_outline_data(PlanText &plan_text)
|
||||
int64_t index_prefix = index_prefix_;
|
||||
ObItemType index_type = T_INDEX_HINT;
|
||||
const ObDMLStmt *stmt = NULL;
|
||||
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
|
||||
bool use_desc_hint = get_scan_direction() == default_desc_direction();
|
||||
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt()) ||
|
||||
OB_ISNULL(stmt->get_query_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected NULl", K(ret), K(get_plan()), K(stmt));
|
||||
} else if (OB_FAIL(stmt->get_qb_name(qb_name))) {
|
||||
@ -2348,19 +2350,22 @@ int ObLogTableScan::print_outline_data(PlanText &plan_text)
|
||||
LOG_WARN("failed to print table parallel hint", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
use_desc_hint &= stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5);
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (is_skip_scan()) {
|
||||
index_type = T_INDEX_SS_HINT;
|
||||
index_type = use_desc_hint ? T_INDEX_SS_DESC_HINT : T_INDEX_SS_HINT;
|
||||
if (ref_table_id_ == index_table_id_) {
|
||||
index_name = &ObIndexHint::PRIMARY_KEY;
|
||||
} else {
|
||||
index_name = &get_index_name();
|
||||
}
|
||||
} else if (ref_table_id_ == index_table_id_ && index_prefix < 0) {
|
||||
} else if (ref_table_id_ == index_table_id_ && index_prefix < 0 && !use_desc_hint) {
|
||||
index_type = T_FULL_HINT;
|
||||
index_name = &ObIndexHint::PRIMARY_KEY;
|
||||
} else {
|
||||
index_type = T_INDEX_HINT;
|
||||
index_type = use_desc_hint ? T_INDEX_DESC_HINT : T_INDEX_HINT;
|
||||
if (ref_table_id_ == index_table_id_) {
|
||||
index_name = &ObIndexHint::PRIMARY_KEY;
|
||||
} else {
|
||||
@ -2466,16 +2471,17 @@ int ObLogTableScan::print_used_hint(PlanText &plan_text)
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected log index hint", K(ret), K(*table_hint));
|
||||
} else if (table_hint->is_use_index_hint()) {// print used use index hint
|
||||
const ObIndexHint *index_hint = NULL;
|
||||
if (ObOptimizerUtil::find_item(table_hint->index_list_, index_table_id_, &idx)) {
|
||||
if (OB_UNLIKELY(idx < 0 || idx >= table_hint->index_list_.count())
|
||||
|| OB_ISNULL(hint = table_hint->index_hints_.at(idx))) {
|
||||
|| OB_ISNULL(index_hint = static_cast<const ObIndexHint *>(table_hint->index_hints_.at(idx)))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected idx", K(ret), K(idx), K(table_hint->index_list_));
|
||||
} else if (!is_skip_scan() && T_INDEX_SS_HINT == hint->get_hint_type()) {
|
||||
} else if (!is_skip_scan() && index_hint->use_skip_scan()) {
|
||||
/* is not index skip scan but exist index_ss hint */
|
||||
} else if (hint->is_trans_added()) {
|
||||
} else if (index_hint->is_trans_added()) {
|
||||
//do nothing
|
||||
} else if (OB_FAIL(hint->print_hint(plan_text))) {
|
||||
} else if (OB_FAIL(index_hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print index hint", K(ret), K(*hint));
|
||||
}
|
||||
}
|
||||
@ -4166,3 +4172,33 @@ int ObLogTableScan::copy_gen_col_range_exprs()
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogTableScan::try_adjust_scan_direction(const ObIArray<OrderItem> &sort_keys)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool order_used = false;
|
||||
const AccessPath *path = NULL;
|
||||
if (OB_ISNULL(path = get_access_path())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(path));
|
||||
} else if (sort_keys.empty() || path->ordering_.empty() ||
|
||||
path->force_direction_ || use_batch()) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(check_op_orderding_used_by_parent(order_used))) {
|
||||
LOG_WARN("failed to check op ordering", K(ret));
|
||||
} else if (!order_used) {
|
||||
const OrderItem &first_sortkey = sort_keys.at(0);
|
||||
bool found = false;
|
||||
bool need_reverse = false;
|
||||
for (int64_t i = 0; !found && i < path->ordering_.count(); i ++) {
|
||||
const OrderItem &path_order = path->ordering_.at(i);
|
||||
if (path_order.expr_ == first_sortkey.expr_) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && found) {
|
||||
set_scan_direction(first_sortkey.order_type_);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -745,6 +745,7 @@ public:
|
||||
|
||||
int copy_gen_col_range_exprs();
|
||||
inline bool need_replace_gen_column() { return !(is_index_scan() && !(get_index_back())); }
|
||||
int try_adjust_scan_direction(const ObIArray<OrderItem> &sort_keys);
|
||||
private: // member functions
|
||||
//called when index_back_ set
|
||||
int pick_out_query_range_exprs();
|
||||
|
@ -1577,6 +1577,19 @@ int ObLogicalOperator::do_pre_traverse_operation(const TraverseOp &op, void *ctx
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADJUST_SCAN_DIRECTION: {
|
||||
if (LOG_SORT == get_type()) {
|
||||
ObLogSort *log_sort = static_cast<ObLogSort *>(this);
|
||||
if (NULL != log_sort->get_topn_filter_node() &&
|
||||
LOG_TABLE_SCAN == log_sort->get_topn_filter_node()->get_type()) {
|
||||
ObLogTableScan *log_tsc = static_cast<ObLogTableScan *>(log_sort->get_topn_filter_node());
|
||||
if (OB_FAIL(log_tsc->try_adjust_scan_direction(log_sort->get_sort_keys()))) {
|
||||
LOG_WARN("failed to adjust table scan direction", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Unexpected access of default branch", K(op), K(ret));
|
||||
@ -1718,6 +1731,9 @@ int ObLogicalOperator::do_post_traverse_operation(const TraverseOp &op, void *ct
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADJUST_SCAN_DIRECTION: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ namespace sql
|
||||
|
||||
COLLECT_BATCH_EXEC_PARAM,
|
||||
ALLOC_OP,
|
||||
ADJUST_SCAN_DIRECTION,
|
||||
TRAVERSE_OP_END
|
||||
};
|
||||
|
||||
|
@ -998,6 +998,8 @@ Timestamp{whitespace}?\"[^\"]*\" {
|
||||
}
|
||||
}
|
||||
<hint>INDEX { return INDEX_HINT; }
|
||||
<hint>INDEX_ASC { return INDEX_ASC_HINT; }
|
||||
<hint>INDEX_DESC { return INDEX_DESC_HINT; }
|
||||
<hint>NO_INDEX { return NO_INDEX_HINT; }
|
||||
<hint>UNION_MERGE { return UNION_MERGE_HINT; }
|
||||
<hint>USE_DAS { return USE_DAS_HINT; }
|
||||
|
@ -183,7 +183,7 @@ COALESCE_AGGR NO_COALESCE_AGGR WITH_PULLUP WO_PULLUP
|
||||
MV_REWRITE NO_MV_REWRITE TRANSFORM_DISTINCT_AGG NO_TRANSFORM_DISTINCT_AGG
|
||||
DECORRELATE NO_DECORRELATE
|
||||
// optimize hint
|
||||
INDEX_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT UNION_MERGE_HINT
|
||||
INDEX_HINT INDEX_ASC_HINT INDEX_DESC_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT UNION_MERGE_HINT
|
||||
INDEX_SS_HINT INDEX_SS_ASC_HINT INDEX_SS_DESC_HINT
|
||||
USE_COLUMN_STORE_HINT NO_USE_COLUMN_STORE_HINT
|
||||
LEADING_HINT ORDERED
|
||||
@ -11825,6 +11825,14 @@ INDEX_HINT '(' qb_name_option relation_factor_in_hint NAME_OB opt_index_prefix '
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_HINT, 4, $3, $4, $5,$6);
|
||||
}
|
||||
| INDEX_ASC_HINT '(' qb_name_option relation_factor_in_hint NAME_OB opt_index_prefix ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_ASC_HINT, 4, $3, $4, $5,$6);
|
||||
}
|
||||
| INDEX_DESC_HINT '(' qb_name_option relation_factor_in_hint NAME_OB opt_index_prefix ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_INDEX_DESC_HINT, 4, $3, $4, $5,$6);
|
||||
}
|
||||
| NO_INDEX_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_NO_INDEX_HINT, 3, $3, $4, $5);
|
||||
|
@ -15191,7 +15191,9 @@ int ObDMLResolver::resolve_optimize_hint(const ParseNode &hint_node,
|
||||
case T_INDEX_SS_ASC_HINT:
|
||||
case T_INDEX_SS_DESC_HINT:
|
||||
case T_USE_COLUMN_STORE_HINT:
|
||||
case T_NO_USE_COLUMN_STORE_HINT: {
|
||||
case T_NO_USE_COLUMN_STORE_HINT:
|
||||
case T_INDEX_ASC_HINT:
|
||||
case T_INDEX_DESC_HINT: {
|
||||
if (OB_FAIL(resolve_index_hint(hint_node, opt_hint))) {
|
||||
LOG_WARN("failed to resolve index hint", K(ret));
|
||||
}
|
||||
@ -15375,12 +15377,14 @@ int ObDMLResolver::resolve_index_hint(const ParseNode &index_node,
|
||||
LOG_WARN("unexpected index hint", K(ret), K(index_node.type_), K(index_node.num_child_),
|
||||
K(index_name_node));
|
||||
} else {
|
||||
//T_NO_INDEX or T_INDEX_HINT
|
||||
//T_NO_INDEX or T_INDEX_HINT or T_INDEX_ASC_HINT or T_INDEX_DESC_HINT
|
||||
index_hint->set_qb_name(qb_name);
|
||||
index_hint->get_index_name().assign_ptr(index_name_node->str_value_,
|
||||
static_cast<int32_t>(index_name_node->str_len_));
|
||||
opt_hint = index_hint;
|
||||
if (T_INDEX_HINT == index_hint->get_hint_type()) {
|
||||
if (T_INDEX_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_DESC_HINT == index_hint->get_hint_type()) {
|
||||
if (OB_UNLIKELY(4 != index_node.num_child_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected index hint", K(ret), K(index_node.type_), K(index_node.num_child_),
|
||||
|
@ -1355,6 +1355,8 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul
|
||||
case T_PQ_SUBQUERY: return "PQ_SUBQUERY";
|
||||
case T_PQ_GBY_HINT: return "PQ_GBY";
|
||||
case T_PQ_DISTINCT_HINT: return "PQ_DISTINCT";
|
||||
case T_INDEX_ASC_HINT: return "INDEX_ASC";
|
||||
case T_INDEX_DESC_HINT: return "INDEX_DESC";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -2335,7 +2337,8 @@ int ObIndexHint::print_hint_desc(PlanText &plan_text) const
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(BUF_PRINTF(" \"%.*s\"", index_name_.length(), index_name_.ptr()))) {
|
||||
LOG_WARN("fail to print index name", K(ret));
|
||||
} else if (T_INDEX_HINT != hint_type_ || index_prefix_ < 0) {
|
||||
} else if ((T_INDEX_HINT != hint_type_ && T_INDEX_ASC_HINT != hint_type_ && T_INDEX_DESC_HINT != hint_type_)
|
||||
|| index_prefix_ < 0) {
|
||||
//do nothing
|
||||
} else if (OB_FAIL(BUF_PRINTF(" %ld", index_prefix_))) {
|
||||
LOG_WARN("fail to print index prefix", K(ret));
|
||||
|
@ -1031,10 +1031,28 @@ public:
|
||||
int64_t &get_index_prefix() { return index_prefix_; }
|
||||
const int64_t &get_index_prefix() const { return index_prefix_; }
|
||||
bool is_use_index_hint() const { return T_NO_INDEX_HINT != get_hint_type(); }
|
||||
bool use_skip_scan() const { return T_INDEX_SS_HINT == get_hint_type(); }
|
||||
bool use_skip_scan() const { return T_INDEX_SS_HINT == get_hint_type() ||
|
||||
T_INDEX_SS_ASC_HINT == get_hint_type() ||
|
||||
T_INDEX_SS_DESC_HINT == get_hint_type(); }
|
||||
bool is_match_index(const ObCollationType cs_type,
|
||||
const TableItem &ref_table,
|
||||
const ObTableSchema &index_schema) const;
|
||||
bool is_asc_hint() const
|
||||
{
|
||||
return T_INDEX_ASC_HINT == get_hint_type() ||
|
||||
T_INDEX_SS_ASC_HINT == get_hint_type();
|
||||
}
|
||||
bool is_desc_hint() const
|
||||
{
|
||||
return T_INDEX_DESC_HINT == get_hint_type() ||
|
||||
T_INDEX_SS_DESC_HINT == get_hint_type();
|
||||
}
|
||||
bool is_unordered_hint() const
|
||||
{
|
||||
return T_INDEX_HINT == get_hint_type() ||
|
||||
T_INDEX_SS_HINT == get_hint_type() ||
|
||||
T_FULL_HINT == get_hint_type();
|
||||
}
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table), K_(index_name), K_(index_prefix));
|
||||
|
||||
|
@ -1942,6 +1942,39 @@ int ObLogPlanHint::check_use_skip_scan(uint64_t table_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlanHint::check_scan_direction(const ObQueryCtx &ctx,
|
||||
uint64_t table_id,
|
||||
uint64_t index_id,
|
||||
ObOrderDirection &direction) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
direction = ObOrderDirection::UNORDERED;
|
||||
const LogTableHint *log_table_hint = get_log_table_hint(table_id);
|
||||
int64_t pos = OB_INVALID_INDEX;
|
||||
static const uint64_t index_desc_enable_version = COMPAT_VERSION_4_3_5;
|
||||
if (!ctx.check_opt_compat_version(index_desc_enable_version)) {
|
||||
direction = ObOrderDirection::UNORDERED;
|
||||
} else if (NULL != log_table_hint &&
|
||||
ObOptimizerUtil::find_item(log_table_hint->index_list_, index_id, &pos)) {
|
||||
const ObIndexHint *hint = NULL;
|
||||
if (OB_UNLIKELY(pos >= log_table_hint->index_hints_.count() || pos < 0)
|
||||
|| OB_ISNULL(hint = log_table_hint->index_hints_.at(pos))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected pos", K(ret), K(pos), K(log_table_hint->index_hints_.count()), K(hint));
|
||||
} else if (hint->is_asc_hint()) {
|
||||
direction = default_asc_direction();
|
||||
} else if (hint->is_desc_hint()) {
|
||||
direction = default_desc_direction();
|
||||
} else if (is_outline_data_ &&
|
||||
hint->is_unordered_hint()) {
|
||||
direction = default_asc_direction();
|
||||
} else {
|
||||
direction = ObOrderDirection::UNORDERED;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ObTableDynamicSamplingHint *ObLogPlanHint::get_dynamic_sampling_hint(uint64_t table_id) const
|
||||
{
|
||||
const LogTableHint *log_table_hint = get_log_table_hint(table_id);
|
||||
@ -2498,7 +2531,11 @@ int LogTableHint::init_index_hints(ObSqlSchemaGuard &schema_guard)
|
||||
if (OB_SUCC(ret) && (!index_name.empty())) {
|
||||
int64_t no_index_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_asc_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_desc_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_ss_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_ss_asc_hint_pos = OB_INVALID_INDEX;
|
||||
int64_t index_ss_desc_hint_pos = OB_INVALID_INDEX;
|
||||
const uint64_t N = index_hints_.count();
|
||||
const ObIndexHint *index_hint = NULL;
|
||||
for (int64_t hint_i = 0; OB_SUCC(ret) && hint_i < N; ++hint_i) {
|
||||
@ -2512,10 +2549,40 @@ int LogTableHint::init_index_hints(ObSqlSchemaGuard &schema_guard)
|
||||
/* do nothing */
|
||||
} else if (T_NO_INDEX_HINT == index_hint->get_hint_type()) {
|
||||
no_index_hint_pos = hint_i;
|
||||
} else if (T_INDEX_SS_HINT == index_hint->get_hint_type()) {
|
||||
index_ss_hint_pos = hint_i;
|
||||
} else if (index_hint->use_skip_scan()) {
|
||||
if (index_hint->is_asc_hint()) {
|
||||
index_ss_asc_hint_pos = hint_i;
|
||||
} else if (index_hint->is_desc_hint()) {
|
||||
index_ss_desc_hint_pos = hint_i;
|
||||
} else {
|
||||
index_ss_hint_pos = hint_i;
|
||||
}
|
||||
} else {
|
||||
index_hint_pos = hint_i;
|
||||
if (index_hint->is_asc_hint()) {
|
||||
index_asc_hint_pos = hint_i;
|
||||
} else if (index_hint->is_desc_hint()) {
|
||||
index_desc_hint_pos = hint_i;
|
||||
} else {
|
||||
index_hint_pos = hint_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_INVALID_INDEX != index_asc_hint_pos &&
|
||||
OB_INVALID_INDEX != index_desc_hint_pos) {
|
||||
// ignore both asc and desc hint if both are present
|
||||
} else if (OB_INVALID_INDEX != index_asc_hint_pos) {
|
||||
index_hint_pos = index_asc_hint_pos;
|
||||
} else if (OB_INVALID_INDEX != index_desc_hint_pos) {
|
||||
index_hint_pos = index_desc_hint_pos;
|
||||
}
|
||||
if (OB_INVALID_INDEX != index_ss_asc_hint_pos &&
|
||||
OB_INVALID_INDEX != index_ss_desc_hint_pos) {
|
||||
// ignore both asc and desc hint if both are present
|
||||
} else if (OB_INVALID_INDEX != index_ss_asc_hint_pos) {
|
||||
index_ss_hint_pos = index_ss_asc_hint_pos;
|
||||
} else if (OB_INVALID_INDEX != index_ss_desc_hint_pos) {
|
||||
index_ss_hint_pos = index_ss_desc_hint_pos;
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
@ -2713,7 +2780,9 @@ int LogTableHint::get_index_prefix(const uint64_t index_id, int64_t &index_prefi
|
||||
} else if (OB_ISNULL(index_hints_.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(i), K(index_hints_));
|
||||
} else if (T_INDEX_HINT == index_hints_.at(i)->get_hint_type()) {
|
||||
} else if (T_INDEX_HINT == index_hints_.at(i)->get_hint_type() ||
|
||||
T_INDEX_ASC_HINT == index_hints_.at(i)->get_hint_type() ||
|
||||
T_INDEX_DESC_HINT == index_hints_.at(i)->get_hint_type()) {
|
||||
index_prefix = index_hints_.at(i)->get_index_prefix();
|
||||
}
|
||||
}
|
||||
|
@ -464,6 +464,10 @@ struct ObLogPlanHint
|
||||
int check_use_skip_scan(uint64_t table_id, uint64_t index_id,
|
||||
bool &force_skip_scan,
|
||||
bool &force_no_skip_scan) const;
|
||||
int check_scan_direction(const ObQueryCtx &ctx,
|
||||
uint64_t table_id,
|
||||
uint64_t index_id,
|
||||
ObOrderDirection &direction) const;
|
||||
const LogJoinHint* get_join_hint(const ObRelIds &join_tables) const;
|
||||
const ObIArray<LogJoinHint> &get_join_hints() const { return join_hints_; }
|
||||
SetAlgo get_valid_set_algo() const;
|
||||
|
@ -371,6 +371,8 @@ int ObTransformLateMaterialization::get_accessible_index(const ObSelectStmt &sel
|
||||
} else if (FALSE_IT(index_hint = static_cast<ObIndexHint *>(opt_hints.at(i)))) {
|
||||
/* do nothing */
|
||||
} else if (T_INDEX_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_DESC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_DESC_HINT == index_hint->get_hint_type()) {
|
||||
@ -962,6 +964,8 @@ int ObTransformLateMaterialization::generate_late_materialization_hint(
|
||||
} else if (hint->is_access_path_hint()) {
|
||||
ObIndexHint *index_hint = static_cast<ObIndexHint *>(hint);
|
||||
if ((T_INDEX_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_DESC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_DESC_HINT == index_hint->get_hint_type() ||
|
||||
@ -982,6 +986,8 @@ int ObTransformLateMaterialization::generate_late_materialization_hint(
|
||||
} else if (hint->is_access_path_hint()) {
|
||||
ObIndexHint *index_hint = static_cast<ObIndexHint *>(hint);
|
||||
if ((T_INDEX_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_DESC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_ASC_HINT == index_hint->get_hint_type() ||
|
||||
T_INDEX_SS_DESC_HINT == index_hint->get_hint_type() ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user