54
54
* Portions Copyright (c) 1994, Regents of the University of California
55
55
*
56
56
* IDENTIFICATION
57
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.167 2006/10/04 00:29:53 momjian Exp $
57
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.168 2006/11/10 01:21:41 tgl Exp $
58
58
*
59
59
*-------------------------------------------------------------------------
60
60
*/
@@ -1948,7 +1948,8 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
1948
1948
JoinType jointype ,
1949
1949
List * restrictlist )
1950
1950
{
1951
- Selectivity selec ;
1951
+ Selectivity jselec ;
1952
+ Selectivity pselec ;
1952
1953
double nrows ;
1953
1954
UniquePath * upath ;
1954
1955
@@ -1957,20 +1958,60 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
1957
1958
* clauses that become restriction clauses at this join level; we are not
1958
1959
* double-counting them because they were not considered in estimating the
1959
1960
* sizes of the component rels.
1961
+ *
1962
+ * For an outer join, we have to distinguish the selectivity of the
1963
+ * join's own clauses (JOIN/ON conditions) from any clauses that were
1964
+ * "pushed down". For inner joins we just count them all as joinclauses.
1960
1965
*/
1961
- selec = clauselist_selectivity (root ,
1962
- restrictlist ,
1963
- 0 ,
1964
- jointype );
1966
+ if (IS_OUTER_JOIN (jointype ))
1967
+ {
1968
+ List * joinquals = NIL ;
1969
+ List * pushedquals = NIL ;
1970
+ ListCell * l ;
1971
+
1972
+ /* Grovel through the clauses to separate into two lists */
1973
+ foreach (l , restrictlist )
1974
+ {
1975
+ RestrictInfo * rinfo = (RestrictInfo * ) lfirst (l );
1976
+
1977
+ Assert (IsA (rinfo , RestrictInfo ));
1978
+ if (rinfo -> is_pushed_down )
1979
+ pushedquals = lappend (pushedquals , rinfo );
1980
+ else
1981
+ joinquals = lappend (joinquals , rinfo );
1982
+ }
1983
+
1984
+ /* Get the separate selectivities */
1985
+ jselec = clauselist_selectivity (root ,
1986
+ joinquals ,
1987
+ 0 ,
1988
+ jointype );
1989
+ pselec = clauselist_selectivity (root ,
1990
+ pushedquals ,
1991
+ 0 ,
1992
+ jointype );
1993
+
1994
+ /* Avoid leaking a lot of ListCells */
1995
+ list_free (joinquals );
1996
+ list_free (pushedquals );
1997
+ }
1998
+ else
1999
+ {
2000
+ jselec = clauselist_selectivity (root ,
2001
+ restrictlist ,
2002
+ 0 ,
2003
+ jointype );
2004
+ pselec = 0.0 ; /* not used, keep compiler quiet */
2005
+ }
1965
2006
1966
2007
/*
1967
2008
* Basically, we multiply size of Cartesian product by selectivity.
1968
2009
*
1969
- * If we are doing an outer join, take that into account: the output must
1970
- * be at least as large as the non-nullable input. (Is there any chance
1971
- * of being even smarter?) (XXX this is not really right, because it
1972
- * assumes all the restriction clauses are join clauses; we should figure
1973
- * pushed-down clauses separately.)
2010
+ * If we are doing an outer join, take that into account: the joinqual
2011
+ * selectivity has to be clamped using the knowledge that the output must
2012
+ * be at least as large as the non-nullable input. However, any
2013
+ * pushed-down quals are applied after the outer join, so their
2014
+ * selectivity applies fully.
1974
2015
*
1975
2016
* For JOIN_IN and variants, the Cartesian product is figured with respect
1976
2017
* to a unique-ified input, and then we can clamp to the size of the other
@@ -1979,38 +2020,41 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
1979
2020
switch (jointype )
1980
2021
{
1981
2022
case JOIN_INNER :
1982
- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2023
+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
1983
2024
break ;
1984
2025
case JOIN_LEFT :
1985
- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2026
+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
1986
2027
if (nrows < outer_rel -> rows )
1987
2028
nrows = outer_rel -> rows ;
2029
+ nrows *= pselec ;
1988
2030
break ;
1989
2031
case JOIN_RIGHT :
1990
- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2032
+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
1991
2033
if (nrows < inner_rel -> rows )
1992
2034
nrows = inner_rel -> rows ;
2035
+ nrows *= pselec ;
1993
2036
break ;
1994
2037
case JOIN_FULL :
1995
- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2038
+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
1996
2039
if (nrows < outer_rel -> rows )
1997
2040
nrows = outer_rel -> rows ;
1998
2041
if (nrows < inner_rel -> rows )
1999
2042
nrows = inner_rel -> rows ;
2043
+ nrows *= pselec ;
2000
2044
break ;
2001
2045
case JOIN_IN :
2002
2046
case JOIN_UNIQUE_INNER :
2003
2047
upath = create_unique_path (root , inner_rel ,
2004
2048
inner_rel -> cheapest_total_path );
2005
- nrows = outer_rel -> rows * upath -> rows * selec ;
2049
+ nrows = outer_rel -> rows * upath -> rows * jselec ;
2006
2050
if (nrows > outer_rel -> rows )
2007
2051
nrows = outer_rel -> rows ;
2008
2052
break ;
2009
2053
case JOIN_REVERSE_IN :
2010
2054
case JOIN_UNIQUE_OUTER :
2011
2055
upath = create_unique_path (root , outer_rel ,
2012
2056
outer_rel -> cheapest_total_path );
2013
- nrows = upath -> rows * inner_rel -> rows * selec ;
2057
+ nrows = upath -> rows * inner_rel -> rows * jselec ;
2014
2058
if (nrows > inner_rel -> rows )
2015
2059
nrows = inner_rel -> rows ;
2016
2060
break ;
0 commit comments