Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7741dd6

Browse files
committed
Recognize self-contradictory restriction clauses for non-table relations.
The constraint exclusion feature checks for contradictions among scanrestriction clauses, as well as contradictions between those clauses and atable's CHECK constraints. The first aspect of this testing can be usefulfor non-table relations (such as subqueries or functions-in-FROM), but thefeature was coded with only the CHECK case in mind so we were applying itonly to plain-table RTEs. Move the relation_excluded_by_constraints callso that it is applied to all RTEs not just plain tables. With the defaultsetting of constraint_exclusion this results in no extra work, but withconstraint_exclusion = ON we will detect optimizations that we missedbefore (at the cost of more planner cycles than we expended before).Per a gripe from Gunnlaugur Þór Briem. Experimentation withhis example also showed we were not being very bright about the case whereconstraint exclusion is proven within a subquery within UNION ALL, so tweakthe code to allow set_append_rel_pathlist to recognize such cases.
1 parent337c0b0 commit7741dd6

File tree

3 files changed

+45
-22
lines changed

3 files changed

+45
-22
lines changed

‎src/backend/optimizer/path/allpaths.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,18 @@ static void
171171
set_rel_pathlist(PlannerInfo*root,RelOptInfo*rel,
172172
Indexrti,RangeTblEntry*rte)
173173
{
174-
if (rte->inh)
174+
if (rel->reloptkind==RELOPT_BASEREL&&
175+
relation_excluded_by_constraints(root,rel,rte))
176+
{
177+
/*
178+
* We proved we don't need to scan the rel via constraint exclusion,
179+
* so set up a single dummy path for it. Here we only check this for
180+
* regular baserels; if it's an otherrel, CE was already checked in
181+
* set_append_rel_pathlist().
182+
*/
183+
set_dummy_rel_pathlist(rel);
184+
}
185+
elseif (rte->inh)
175186
{
176187
/* It's an "append relation", process accordingly */
177188
set_append_rel_pathlist(root,rel,rti,rte);
@@ -229,19 +240,6 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
229240
staticvoid
230241
set_plain_rel_pathlist(PlannerInfo*root,RelOptInfo*rel,RangeTblEntry*rte)
231242
{
232-
/*
233-
* If we can prove we don't need to scan the rel via constraint exclusion,
234-
* set up a single dummy path for it. We only need to check for regular
235-
* baserels; if it's an otherrel, CE was already checked in
236-
* set_append_rel_pathlist().
237-
*/
238-
if (rel->reloptkind==RELOPT_BASEREL&&
239-
relation_excluded_by_constraints(root,rel,rte))
240-
{
241-
set_dummy_rel_pathlist(rel);
242-
return;
243-
}
244-
245243
/*
246244
* Test any partial indexes of rel for applicability. We must do this
247245
* first since partial unique indexes can affect size estimates.
@@ -439,18 +437,29 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
439437
* otherrels. So we just leave the child's attr_needed empty.
440438
*/
441439

442-
/* Remember which childrels are live, for MergeAppend logic below */
443-
live_childrels=lappend(live_childrels,childrel);
444-
445440
/*
446-
* Compute the child's access paths, and add the cheapest one to the
447-
* Append path we are constructing for the parent.
441+
* Compute the child's access paths.
448442
*/
449443
set_rel_pathlist(root,childrel,childRTindex,childRTE);
450444

445+
/*
446+
* It is possible that constraint exclusion detected a contradiction
447+
* within a child subquery, even though we didn't prove one above.
448+
* If what we got back was a dummy path, we can skip this child.
449+
*/
450+
if (IS_DUMMY_PATH(childrel->cheapest_total_path))
451+
continue;
452+
453+
/*
454+
* Child is live, so add its cheapest access path to the Append path
455+
* we are constructing for the parent.
456+
*/
451457
subpaths=accumulate_append_subpath(subpaths,
452458
childrel->cheapest_total_path);
453459

460+
/* Remember which childrels are live, for MergeAppend logic below */
461+
live_childrels=lappend(live_childrels,childrel);
462+
454463
/*
455464
* Collect a list of all the available path orderings for all the
456465
* children. We use this as a heuristic to indicate which sort
@@ -793,6 +802,17 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
793802
&subroot);
794803
rel->subroot=subroot;
795804

805+
/*
806+
* It's possible that constraint exclusion proved the subquery empty.
807+
* If so, it's convenient to turn it back into a dummy path so that we
808+
* will recognize appropriate optimizations at this level.
809+
*/
810+
if (is_dummy_plan(rel->subplan))
811+
{
812+
set_dummy_rel_pathlist(rel);
813+
return;
814+
}
815+
796816
/* Mark rel with estimated output rows, width, etc */
797817
set_subquery_size_estimates(root,rel);
798818

‎src/backend/optimizer/plan/planner.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
6060
staticvoidpreprocess_qual_conditions(PlannerInfo*root,Node*jtnode);
6161
staticPlan*inheritance_planner(PlannerInfo*root);
6262
staticPlan*grouping_planner(PlannerInfo*root,doubletuple_fraction);
63-
staticboolis_dummy_plan(Plan*plan);
6463
staticvoidpreprocess_rowmarks(PlannerInfo*root);
6564
staticdoublepreprocess_limit(PlannerInfo*root,
6665
doubletuple_fraction,
@@ -1841,9 +1840,11 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
18411840
* is deemed not to need scanning due to constraint exclusion.
18421841
*
18431842
* Currently, such dummy plans are Result nodes with constant FALSE
1844-
* filter quals.
1843+
* filter quals (see set_dummy_rel_pathlist and create_append_plan).
1844+
*
1845+
* XXX this probably ought to be somewhere else, but not clear where.
18451846
*/
1846-
staticbool
1847+
bool
18471848
is_dummy_plan(Plan*plan)
18481849
{
18491850
if (IsA(plan,Result))

‎src/include/optimizer/planner.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
3535
boolhasRecursion,doubletuple_fraction,
3636
PlannerInfo**subroot);
3737

38+
externboolis_dummy_plan(Plan*plan);
39+
3840
externExpr*expression_planner(Expr*expr);
3941

4042
externboolplan_cluster_use_sort(OidtableOid,OidindexOid);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp