forked from huawei/openGauss-server
SQL optimization
Offering: openGaussDev More detail: support null_test short circuit # Conflicts: # src/test/regress/parallel_schedule0 Match-id-b136e3ec8a8b1f7983c92aa6c68b395a2ea6bbd7
This commit is contained in:
parent
ab3ee6a00a
commit
3bb32d1d4a
|
@ -222,6 +222,8 @@ static bool relIsDeltaNode(PlannerInfo* root, RelOptInfo* relOptInfo);
|
|||
|
||||
static void ModifyWorktableWtParam(Node* planNode, int oldWtParam, int newWtParam);
|
||||
|
||||
static bool ScanQualsViolateNotNullConstr(PlannerInfo* root, RelOptInfo* rel, Path* best_path);
|
||||
|
||||
#define SATISFY_INFORMATIONAL_CONSTRAINT(joinPlan, joinType) \
|
||||
(u_sess->attr.attr_sql.enable_constraint_optimization && true == innerPlan((joinPlan))->hasUniqueResults && \
|
||||
JOIN_SEMI != (joinType) && JOIN_ANTI != (joinType))
|
||||
|
@ -752,11 +754,49 @@ static Plan* create_scan_plan(PlannerInfo* root, Path* best_path)
|
|||
*/
|
||||
if (root->hasPseudoConstantQuals) {
|
||||
plan = create_gating_plan(root, plan, scan_clauses);
|
||||
} else if (ScanQualsViolateNotNullConstr(root, rel, best_path)) {
|
||||
/*
|
||||
* If there is IS NULL qual on a known NOT-NULL attribute, insert a Result node to prevent needless execution.
|
||||
*/
|
||||
plan = (Plan*)make_result(root, plan->targetlist, (Node*)list_make1(makeBoolConst(false, false)), plan);
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
static bool IsScanPath(NodeTag type)
|
||||
{
|
||||
return (
|
||||
type == T_CStoreScan || type == T_CStoreIndexScan || type == T_CStoreIndexHeapScan || type == T_SeqScan ||
|
||||
type == T_DfsScan || type == T_IndexScan || type == T_IndexOnlyScan || type == T_BitmapHeapScan
|
||||
);
|
||||
}
|
||||
|
||||
static bool ScanQualsViolateNotNullConstr(PlannerInfo* root, RelOptInfo* rel, Path* best_path)
|
||||
{
|
||||
/* For now, we only support table scan optimization */
|
||||
if (rel->rtekind != RTE_RELATION || !IsScanPath(best_path->pathtype)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List* scan_clauses = rel->baserestrictinfo;
|
||||
ListCell* lc = NULL;
|
||||
foreach (lc, scan_clauses) {
|
||||
Node* clause = (Node*)lfirst(lc);
|
||||
if (IsA(clause, RestrictInfo) && IsA(((RestrictInfo*)clause)->clause, NullTest)) {
|
||||
NullTest* expr = (NullTest*)((RestrictInfo*)clause)->clause;
|
||||
/* For attribute with NOT-NULL constraint, IS-NULL expression can be short-circuited */
|
||||
if (expr->nulltesttype != IS_NULL || !IsA(expr->arg, Var)) {
|
||||
continue;
|
||||
}
|
||||
if (check_var_nonnullable(root->parse, (Node*)expr->arg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a target list (ie, a list of TargetEntry) for a relation.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
create schema null_test_opt_nsp;
|
||||
set search_path = null_test_opt_nsp;
|
||||
create table t(a int, b int not null);
|
||||
insert into t values(1, 1);
|
||||
explain (costs off) select * from t where b is null order by 1, 2;
|
||||
QUERY PLAN
|
||||
-----------------------------------
|
||||
Sort
|
||||
Sort Key: a, b
|
||||
-> Result
|
||||
One-Time Filter: false
|
||||
-> Seq Scan on t
|
||||
Filter: (b IS NULL)
|
||||
(6 rows)
|
||||
|
||||
select * from t where b is null order by 1, 2;
|
||||
a | b
|
||||
---+---
|
||||
(0 rows)
|
||||
|
||||
explain (costs off) select * from t where b is not null order by 1, 2;
|
||||
QUERY PLAN
|
||||
---------------------
|
||||
Sort
|
||||
Sort Key: a, b
|
||||
-> Seq Scan on t
|
||||
(3 rows)
|
||||
|
||||
select * from t where b is not null order by 1, 2;
|
||||
a | b
|
||||
---+---
|
||||
1 | 1
|
||||
(1 row)
|
||||
|
||||
explain (costs off) select * from t where b is null or b is not null order by 1, 2;
|
||||
QUERY PLAN
|
||||
---------------------
|
||||
Sort
|
||||
Sort Key: a, b
|
||||
-> Seq Scan on t
|
||||
(3 rows)
|
||||
|
||||
select * from t where b is null or b is not null order by 1, 2;
|
||||
a | b
|
||||
---+---
|
||||
1 | 1
|
||||
(1 row)
|
||||
|
||||
explain (costs off) select * from t where b is null or a = 1 order by 1, 2;
|
||||
QUERY PLAN
|
||||
------------------------------------------
|
||||
Sort
|
||||
Sort Key: a, b
|
||||
-> Seq Scan on t
|
||||
Filter: ((b IS NULL) OR (a = 1))
|
||||
(4 rows)
|
||||
|
||||
select * from t where b is null or a = 1 order by 1, 2;
|
||||
a | b
|
||||
---+---
|
||||
1 | 1
|
||||
(1 row)
|
||||
|
||||
explain (costs off) select * from t where b is null and a = 1 order by 1, 2;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------
|
||||
Sort
|
||||
Sort Key: b
|
||||
-> Result
|
||||
One-Time Filter: false
|
||||
-> Seq Scan on t
|
||||
Filter: ((b IS NULL) AND (a = 1))
|
||||
(6 rows)
|
||||
|
||||
select * from t where b is null and a = 1 order by 1, 2;
|
||||
a | b
|
||||
---+---
|
||||
(0 rows)
|
||||
|
||||
explain (costs off) select * from t tt1 join t tt2 on tt1.a = tt2.b where tt1.a is null;
|
||||
QUERY PLAN
|
||||
-----------------------------------------
|
||||
Hash Join
|
||||
Hash Cond: (tt1.a = tt2.b)
|
||||
-> Seq Scan on t tt1
|
||||
Filter: (a IS NULL)
|
||||
-> Hash
|
||||
-> Result
|
||||
One-Time Filter: false
|
||||
-> Seq Scan on t tt2
|
||||
Filter: (b IS NULL)
|
||||
(9 rows)
|
||||
|
||||
select * from t tt1 join t tt2 on tt1.a = tt2.b where tt1.a is null;
|
||||
a | b | a | b
|
||||
---+---+---+---
|
||||
(0 rows)
|
||||
|
||||
drop schema null_test_opt_nsp cascade;
|
||||
NOTICE: drop cascades to table t
|
|
@ -25,8 +25,8 @@ test: pldeveloper_gs_source
|
|||
test: index_advisor
|
||||
test: pl_debugger_server pl_debugger_client
|
||||
test: update_for_wait_s1 update_for_wait_s2
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud
|
||||
test: large_sequence int16 gs_dump_sequence
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt
|
||||
test: large_sequence int16 forall_save_exceptions gs_dump_sequence
|
||||
test: gs_dump_tableof
|
||||
test: analyze_commands
|
||||
#test: single_node_job
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
create schema null_test_opt_nsp;
|
||||
|
||||
set search_path = null_test_opt_nsp;
|
||||
|
||||
create table t(a int, b int not null);
|
||||
|
||||
insert into t values(1, 1);
|
||||
|
||||
explain (costs off) select * from t where b is null order by 1, 2;
|
||||
|
||||
select * from t where b is null order by 1, 2;
|
||||
|
||||
explain (costs off) select * from t where b is not null order by 1, 2;
|
||||
|
||||
select * from t where b is not null order by 1, 2;
|
||||
|
||||
explain (costs off) select * from t where b is null or b is not null order by 1, 2;
|
||||
|
||||
select * from t where b is null or b is not null order by 1, 2;
|
||||
|
||||
explain (costs off) select * from t where b is null or a = 1 order by 1, 2;
|
||||
|
||||
select * from t where b is null or a = 1 order by 1, 2;
|
||||
|
||||
explain (costs off) select * from t where b is null and a = 1 order by 1, 2;
|
||||
|
||||
select * from t where b is null and a = 1 order by 1, 2;
|
||||
|
||||
explain (costs off) select * from t tt1 join t tt2 on tt1.a = tt2.b where tt1.a is null;
|
||||
|
||||
select * from t tt1 join t tt2 on tt1.a = tt2.b where tt1.a is null;
|
||||
|
||||
drop schema null_test_opt_nsp cascade;
|
Loading…
Reference in New Issue