aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/selfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/selfuncs.c')
-rw-r--r--src/backend/utils/adt/selfuncs.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 3ab3881c257..e0cfeefaee4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.94 2001/06/25 21:11:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.95 2001/07/16 05:06:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -86,6 +86,7 @@
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/plancat.h"
+#include "optimizer/prep.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parsetree.h"
@@ -2950,24 +2951,63 @@ genericcostestimate(Query *root, RelOptInfo *rel,
{
double numIndexTuples;
double numIndexPages;
+ List *selectivityQuals = indexQuals;
- /* Estimate the fraction of main-table tuples that will be visited */
- *indexSelectivity = clauselist_selectivity(root, indexQuals,
- lfirsti(rel->relids));
+ /*
+ * If the index is partial, AND the index predicate with the explicitly
+ * given indexquals to produce a more accurate idea of the index
+ * restriction. This may produce redundant clauses, which we hope that
+ * cnfify and clauselist_selectivity will deal with intelligently.
+ *
+ * Note that index->indpred and indexQuals are both in implicit-AND
+ * form to start with, which we have to make explicit to hand to
+ * canonicalize_qual, and then we get back implicit-AND form again.
+ */
+ if (index->indpred != NIL)
+ {
+ Expr *andedQuals;
- /* Estimate the number of index tuples that will be visited */
- numIndexTuples = *indexSelectivity * index->tuples;
+ andedQuals = make_ands_explicit(nconc(listCopy(index->indpred),
+ indexQuals));
+ selectivityQuals = canonicalize_qual(andedQuals, true);
+ }
- /* Estimate the number of index pages that will be retrieved */
- numIndexPages = *indexSelectivity * index->pages;
+ /* Estimate the fraction of main-table tuples that will be visited */
+ *indexSelectivity = clauselist_selectivity(root, selectivityQuals,
+ lfirsti(rel->relids));
/*
- * Always estimate at least one tuple and page are touched, even when
+ * Estimate the number of tuples that will be visited. We do it in
+ * this rather peculiar-looking way in order to get the right answer
+ * for partial indexes. We can bound the number of tuples by the
+ * index size, in any case.
+ */
+ numIndexTuples = *indexSelectivity * rel->tuples;
+
+ if (numIndexTuples > index->tuples)
+ numIndexTuples = index->tuples;
+
+ /*
+ * Always estimate at least one tuple is touched, even when
* indexSelectivity estimate is tiny.
*/
if (numIndexTuples < 1.0)
numIndexTuples = 1.0;
- if (numIndexPages < 1.0)
+
+ /*
+ * Estimate the number of index pages that will be retrieved.
+ *
+ * For all currently-supported index types, the first page of the index
+ * is a metadata page, and we should figure on fetching that plus a
+ * pro-rated fraction of the remaining pages.
+ */
+ if (index->pages > 1 && index->tuples > 0)
+ {
+ numIndexPages = (numIndexTuples / index->tuples) * (index->pages - 1);
+ numIndexPages += 1; /* count the metapage too */
+ numIndexPages = ceil(numIndexPages);
+ }
+ else
numIndexPages = 1.0;
/*