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

Commitfd791e7

Browse files
committed
When a relation has been proven empty by constraint exclusion, propagate that
knowledge up through any joins it participates in. We were doing that alreadyin some special cases but not in the general case. Also, defend against zerorow estimates for the input relations in cost_mergejoin --- this fix may haveeliminated the only scenario in which that can happen, but be safe. Perreport from Alex Solovey.
1 parent2a34672 commitfd791e7

File tree

5 files changed

+113
-11
lines changed

5 files changed

+113
-11
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.168 2008/01/11 04:02:18 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.169 2008/03/24 21:53:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -428,7 +428,7 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
428428
* Build a dummy path for a relation that's been excluded by constraints
429429
*
430430
* Rather than inventing a special "dummy" path type, we represent this as an
431-
* AppendPath with no members.
431+
* AppendPath with no members (see also IS_DUMMY_PATH macro).
432432
*/
433433
staticvoid
434434
set_dummy_rel_pathlist(RelOptInfo*rel)

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
* Portions Copyright (c) 1994, Regents of the University of California
5555
*
5656
* IDENTIFICATION
57-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.191 2008/01/01 19:45:50 momjian Exp $
57+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.192 2008/03/24 21:53:03 tgl Exp $
5858
*
5959
*-------------------------------------------------------------------------
6060
*/
@@ -1385,6 +1385,12 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
13851385
Selectivityjoininfactor;
13861386
Pathsort_path;/* dummy for result of cost_sort */
13871387

1388+
/* Protect some assumptions below that rowcounts aren't zero */
1389+
if (outer_path_rows <=0)
1390+
outer_path_rows=1;
1391+
if (inner_path_rows <=0)
1392+
inner_path_rows=1;
1393+
13881394
if (!enable_mergejoin)
13891395
startup_cost+=disable_cost;
13901396

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.115 2008/01/09 20:42:27 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.116 2008/03/24 21:53:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -837,11 +837,9 @@ best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
837837

838838
/*
839839
* Check to see if child was rejected by constraint exclusion. If so,
840-
* it will have a cheapest_total_path that's an Append path with no
841-
* members (see set_plain_rel_pathlist).
840+
* it will have a cheapest_total_path that's a "dummy" path.
842841
*/
843-
if (IsA(childrel->cheapest_total_path,AppendPath)&&
844-
((AppendPath*)childrel->cheapest_total_path)->subpaths==NIL)
842+
if (IS_DUMMY_PATH(childrel->cheapest_total_path))
845843
continue;/* OK, we can ignore it */
846844

847845
/*

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

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.91 2008/01/11 04:02:18 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.92 2008/03/24 21:53:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -27,6 +27,8 @@ static List *make_rels_by_clauseless_joins(PlannerInfo *root,
2727
ListCell*other_rels);
2828
staticboolhas_join_restriction(PlannerInfo*root,RelOptInfo*rel);
2929
staticboolhas_legal_joinclause(PlannerInfo*root,RelOptInfo*rel);
30+
staticboolis_dummy_rel(RelOptInfo*rel);
31+
staticvoidmark_dummy_join(RelOptInfo*rel);
3032

3133

3234
/*
@@ -571,35 +573,75 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
571573
&restrictlist);
572574

573575
/*
574-
* Consider paths using each rel as both outer and inner.
576+
* If we've already proven this join is empty, we needn't consider
577+
* any more paths for it.
578+
*/
579+
if (is_dummy_rel(joinrel))
580+
{
581+
bms_free(joinrelids);
582+
returnjoinrel;
583+
}
584+
585+
/*
586+
* Consider paths using each rel as both outer and inner. Depending
587+
* on the join type, a provably empty outer or inner rel might mean
588+
* the join is provably empty too; in which case throw away any
589+
* previously computed paths and mark the join as dummy. (We do it
590+
* this way since it's conceivable that dummy-ness of a multi-element
591+
* join might only be noticeable for certain construction paths.)
575592
*/
576593
switch (jointype)
577594
{
578595
caseJOIN_INNER:
596+
if (is_dummy_rel(rel1)||is_dummy_rel(rel2))
597+
{
598+
mark_dummy_join(joinrel);
599+
break;
600+
}
579601
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_INNER,
580602
restrictlist);
581603
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_INNER,
582604
restrictlist);
583605
break;
584606
caseJOIN_LEFT:
607+
if (is_dummy_rel(rel1))
608+
{
609+
mark_dummy_join(joinrel);
610+
break;
611+
}
585612
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_LEFT,
586613
restrictlist);
587614
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_RIGHT,
588615
restrictlist);
589616
break;
590617
caseJOIN_FULL:
618+
if (is_dummy_rel(rel1)&&is_dummy_rel(rel2))
619+
{
620+
mark_dummy_join(joinrel);
621+
break;
622+
}
591623
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_FULL,
592624
restrictlist);
593625
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_FULL,
594626
restrictlist);
595627
break;
596628
caseJOIN_RIGHT:
629+
if (is_dummy_rel(rel2))
630+
{
631+
mark_dummy_join(joinrel);
632+
break;
633+
}
597634
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_RIGHT,
598635
restrictlist);
599636
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_LEFT,
600637
restrictlist);
601638
break;
602639
caseJOIN_IN:
640+
if (is_dummy_rel(rel1)||is_dummy_rel(rel2))
641+
{
642+
mark_dummy_join(joinrel);
643+
break;
644+
}
603645
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_IN,
604646
restrictlist);
605647
/* REVERSE_IN isn't supported by joinpath.c */
@@ -609,6 +651,11 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
609651
restrictlist);
610652
break;
611653
caseJOIN_REVERSE_IN:
654+
if (is_dummy_rel(rel1)||is_dummy_rel(rel2))
655+
{
656+
mark_dummy_join(joinrel);
657+
break;
658+
}
612659
/* REVERSE_IN isn't supported by joinpath.c */
613660
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_IN,
614661
restrictlist);
@@ -618,12 +665,22 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
618665
restrictlist);
619666
break;
620667
caseJOIN_UNIQUE_OUTER:
668+
if (is_dummy_rel(rel1)||is_dummy_rel(rel2))
669+
{
670+
mark_dummy_join(joinrel);
671+
break;
672+
}
621673
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_UNIQUE_OUTER,
622674
restrictlist);
623675
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_UNIQUE_INNER,
624676
restrictlist);
625677
break;
626678
caseJOIN_UNIQUE_INNER:
679+
if (is_dummy_rel(rel1)||is_dummy_rel(rel2))
680+
{
681+
mark_dummy_join(joinrel);
682+
break;
683+
}
627684
add_paths_to_joinrel(root,joinrel,rel1,rel2,JOIN_UNIQUE_INNER,
628685
restrictlist);
629686
add_paths_to_joinrel(root,joinrel,rel2,rel1,JOIN_UNIQUE_OUTER,
@@ -883,3 +940,39 @@ has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel)
883940

884941
return false;
885942
}
943+
944+
945+
/*
946+
* is_dummy_rel --- has relation been proven empty?
947+
*
948+
* If so, it will have a single path that is dummy.
949+
*/
950+
staticbool
951+
is_dummy_rel(RelOptInfo*rel)
952+
{
953+
return (rel->cheapest_total_path!=NULL&&
954+
IS_DUMMY_PATH(rel->cheapest_total_path));
955+
}
956+
957+
/*
958+
* Mark a joinrel as proven empty.
959+
*/
960+
staticvoid
961+
mark_dummy_join(RelOptInfo*rel)
962+
{
963+
/* Set dummy size estimate */
964+
rel->rows=0;
965+
966+
/* Evict any previously chosen paths */
967+
rel->pathlist=NIL;
968+
969+
/* Set up the dummy path */
970+
add_path(rel, (Path*)create_append_path(rel,NIL));
971+
972+
/*
973+
* Although set_cheapest will be done again later, we do it immediately
974+
* in order to keep is_dummy_rel as cheap as possible (ie, not have
975+
* to examine the pathlist).
976+
*/
977+
set_cheapest(rel);
978+
}

‎src/include/nodes/relation.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.154 2008/01/11 04:02:18 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.155 2008/03/24 21:53:04 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -693,13 +693,18 @@ typedef struct TidPath
693693
*
694694
* Note: it is possible for "subpaths" to contain only one, or even no,
695695
* elements. These cases are optimized during create_append_plan.
696+
* In particular, an AppendPath with no subpaths is a "dummy" path that
697+
* is created to represent the case that a relation is provably empty.
696698
*/
697699
typedefstructAppendPath
698700
{
699701
Pathpath;
700702
List*subpaths;/* list of component Paths */
701703
}AppendPath;
702704

705+
#defineIS_DUMMY_PATH(p) \
706+
(IsA((p), AppendPath) && ((AppendPath *) (p))->subpaths == NIL)
707+
703708
/*
704709
* ResultPath represents use of a Result plan node to compute a variable-free
705710
* targetlist with no underlying tables (a "SELECT expressions" query).

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp