Skip to content

Commit 0ee53b5

Browse files
committed
Don't return an overoptimistic result from join_in_selectivity when
we have detected that an IN subquery must return unique results.
1 parent 864412f commit 0ee53b5

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

src/backend/optimizer/path/costsize.c

+24-12
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1994, Regents of the University of California
5050
*
5151
* IDENTIFICATION
52-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.122 2004/01/06 04:31:01 tgl Exp $
52+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.123 2004/01/19 03:52:28 tgl Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -763,9 +763,7 @@ cost_nestloop(NestPath *path, Query *root)
763763
* an outer tuple as soon as we have one match. Account for the
764764
* effects of this by scaling down the cost estimates in proportion to
765765
* the JOIN_IN selectivity. (This assumes that all the quals
766-
* attached to the join are IN quals, which should be true.) This would
767-
* probably be the wrong approach if an input path is a UniquePath, but
768-
* we'd never have that with JOIN_IN join type.
766+
* attached to the join are IN quals, which should be true.)
769767
*/
770768
joininfactor = join_in_selectivity(path, root);
771769

@@ -1001,9 +999,7 @@ cost_mergejoin(MergePath *path, Query *root)
1001999
* for an outer tuple as soon as we have one match. Account for the
10021000
* effects of this by scaling down the cost estimates in proportion to
10031001
* the expected output size. (This assumes that all the quals
1004-
* attached to the join are IN quals, which should be true.) This would
1005-
* probably be the wrong approach if an input path is a UniquePath, but
1006-
* we'd never have that with JOIN_IN join type.
1002+
* attached to the join are IN quals, which should be true.)
10071003
*/
10081004
joininfactor = join_in_selectivity(&path->jpath, root);
10091005

@@ -1208,9 +1204,7 @@ cost_hashjoin(HashPath *path, Query *root)
12081204
* an outer tuple as soon as we have one match. Account for the
12091205
* effects of this by scaling down the cost estimates in proportion to
12101206
* the expected output size. (This assumes that all the quals
1211-
* attached to the join are IN quals, which should be true.) This would
1212-
* probably be the wrong approach if an input path is a UniquePath, but
1213-
* we'd never have that with JOIN_IN join type.
1207+
* attached to the join are IN quals, which should be true.)
12141208
*/
12151209
joininfactor = join_in_selectivity(&path->jpath, root);
12161210

@@ -1779,12 +1773,31 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
17791773
static Selectivity
17801774
join_in_selectivity(JoinPath *path, Query *root)
17811775
{
1776+
RelOptInfo *innerrel;
1777+
UniquePath *innerunique;
17821778
Selectivity selec;
17831779
double nrows;
17841780

1781+
/* Return 1.0 whenever it's not JOIN_IN */
17851782
if (path->jointype != JOIN_IN)
17861783
return 1.0;
17871784

1785+
/*
1786+
* Return 1.0 if the inner side is already known unique. The case where
1787+
* the inner path is already a UniquePath probably cannot happen in
1788+
* current usage, but check it anyway for completeness. The interesting
1789+
* case is where we've determined the inner relation itself is unique,
1790+
* which we can check by looking at the rows estimate for its UniquePath.
1791+
*/
1792+
if (IsA(path->innerjoinpath, UniquePath))
1793+
return 1.0;
1794+
innerrel = path->innerjoinpath->parent;
1795+
innerunique = create_unique_path(root,
1796+
innerrel,
1797+
innerrel->cheapest_total_path);
1798+
if (innerunique->rows >= innerrel->rows)
1799+
return 1.0;
1800+
17881801
/*
17891802
* Compute same result set_joinrel_size_estimates would compute
17901803
* for JOIN_INNER. Note that we use the input rels' absolute size
@@ -1796,8 +1809,7 @@ join_in_selectivity(JoinPath *path, Query *root)
17961809
path->joinrestrictinfo,
17971810
0,
17981811
JOIN_INNER);
1799-
nrows = path->outerjoinpath->parent->rows *
1800-
path->innerjoinpath->parent->rows * selec;
1812+
nrows = path->outerjoinpath->parent->rows * innerrel->rows * selec;
18011813

18021814
nrows = clamp_row_est(nrows);
18031815

0 commit comments

Comments
 (0)