Commit 0ee53b5c authored by Tom Lane's avatar Tom Lane

Don't return an overoptimistic result from join_in_selectivity when

we have detected that an IN subquery must return unique results.
parent 864412fd
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.122 2004/01/06 04:31:01 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.123 2004/01/19 03:52:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -763,9 +763,7 @@ cost_nestloop(NestPath *path, Query *root) ...@@ -763,9 +763,7 @@ cost_nestloop(NestPath *path, Query *root)
* an outer tuple as soon as we have one match. Account for the * an outer tuple as soon as we have one match. Account for the
* effects of this by scaling down the cost estimates in proportion to * effects of this by scaling down the cost estimates in proportion to
* the JOIN_IN selectivity. (This assumes that all the quals * the JOIN_IN selectivity. (This assumes that all the quals
* attached to the join are IN quals, which should be true.) This would * attached to the join are IN quals, which should be true.)
* probably be the wrong approach if an input path is a UniquePath, but
* we'd never have that with JOIN_IN join type.
*/ */
joininfactor = join_in_selectivity(path, root); joininfactor = join_in_selectivity(path, root);
...@@ -1001,9 +999,7 @@ cost_mergejoin(MergePath *path, Query *root) ...@@ -1001,9 +999,7 @@ cost_mergejoin(MergePath *path, Query *root)
* for an outer tuple as soon as we have one match. Account for the * for an outer tuple as soon as we have one match. Account for the
* effects of this by scaling down the cost estimates in proportion to * effects of this by scaling down the cost estimates in proportion to
* the expected output size. (This assumes that all the quals * the expected output size. (This assumes that all the quals
* attached to the join are IN quals, which should be true.) This would * attached to the join are IN quals, which should be true.)
* probably be the wrong approach if an input path is a UniquePath, but
* we'd never have that with JOIN_IN join type.
*/ */
joininfactor = join_in_selectivity(&path->jpath, root); joininfactor = join_in_selectivity(&path->jpath, root);
...@@ -1208,9 +1204,7 @@ cost_hashjoin(HashPath *path, Query *root) ...@@ -1208,9 +1204,7 @@ cost_hashjoin(HashPath *path, Query *root)
* an outer tuple as soon as we have one match. Account for the * an outer tuple as soon as we have one match. Account for the
* effects of this by scaling down the cost estimates in proportion to * effects of this by scaling down the cost estimates in proportion to
* the expected output size. (This assumes that all the quals * the expected output size. (This assumes that all the quals
* attached to the join are IN quals, which should be true.) This would * attached to the join are IN quals, which should be true.)
* probably be the wrong approach if an input path is a UniquePath, but
* we'd never have that with JOIN_IN join type.
*/ */
joininfactor = join_in_selectivity(&path->jpath, root); joininfactor = join_in_selectivity(&path->jpath, root);
...@@ -1779,12 +1773,31 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel, ...@@ -1779,12 +1773,31 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
static Selectivity static Selectivity
join_in_selectivity(JoinPath *path, Query *root) join_in_selectivity(JoinPath *path, Query *root)
{ {
RelOptInfo *innerrel;
UniquePath *innerunique;
Selectivity selec; Selectivity selec;
double nrows; double nrows;
/* Return 1.0 whenever it's not JOIN_IN */
if (path->jointype != JOIN_IN) if (path->jointype != JOIN_IN)
return 1.0; return 1.0;
/*
* Return 1.0 if the inner side is already known unique. The case where
* the inner path is already a UniquePath probably cannot happen in
* current usage, but check it anyway for completeness. The interesting
* case is where we've determined the inner relation itself is unique,
* which we can check by looking at the rows estimate for its UniquePath.
*/
if (IsA(path->innerjoinpath, UniquePath))
return 1.0;
innerrel = path->innerjoinpath->parent;
innerunique = create_unique_path(root,
innerrel,
innerrel->cheapest_total_path);
if (innerunique->rows >= innerrel->rows)
return 1.0;
/* /*
* Compute same result set_joinrel_size_estimates would compute * Compute same result set_joinrel_size_estimates would compute
* for JOIN_INNER. Note that we use the input rels' absolute size * for JOIN_INNER. Note that we use the input rels' absolute size
...@@ -1796,8 +1809,7 @@ join_in_selectivity(JoinPath *path, Query *root) ...@@ -1796,8 +1809,7 @@ join_in_selectivity(JoinPath *path, Query *root)
path->joinrestrictinfo, path->joinrestrictinfo,
0, 0,
JOIN_INNER); JOIN_INNER);
nrows = path->outerjoinpath->parent->rows * nrows = path->outerjoinpath->parent->rows * innerrel->rows * selec;
path->innerjoinpath->parent->rows * selec;
nrows = clamp_row_est(nrows); nrows = clamp_row_est(nrows);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment