summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/costsize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/costsize.c')
-rw-r--r--src/backend/optimizer/path/costsize.c81
1 files changed, 70 insertions, 11 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index fffa25dd84..cd289423ec 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.165 2006/08/02 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.166 2006/09/19 22:49:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -288,7 +288,8 @@ cost_index(IndexPath *path, PlannerInfo *root,
pages_fetched = index_pages_fetched(tuples_fetched * num_scans,
baserel->pages,
- index->pages);
+ (double) index->pages,
+ root);
run_cost += (pages_fetched * random_page_cost) / num_scans;
}
@@ -300,7 +301,8 @@ cost_index(IndexPath *path, PlannerInfo *root,
*/
pages_fetched = index_pages_fetched(tuples_fetched,
baserel->pages,
- index->pages);
+ (double) index->pages,
+ root);
/* max_IO_cost is for the perfectly uncorrelated case (csquared=0) */
max_IO_cost = pages_fetched * random_page_cost;
@@ -369,13 +371,18 @@ cost_index(IndexPath *path, PlannerInfo *root,
* b = # buffer pages available (we include kernel space here)
*
* We assume that effective_cache_size is the total number of buffer pages
- * available for both table and index, and pro-rate that space between the
- * table and index. (Ideally other_pages should include all the other
- * tables and indexes used by the query too; but we don't have a good way
- * to get that number here.)
+ * available for the whole query, and pro-rate that space across all the
+ * tables in the query and the index currently under consideration. (This
+ * ignores space needed for other indexes used by the query, but since we
+ * don't know which indexes will get used, we can't estimate that very well;
+ * and in any case counting all the tables may well be an overestimate, since
+ * depending on the join plan not all the tables may be scanned concurrently.)
*
* The product Ns is the number of tuples fetched; we pass in that
- * product rather than calculating it here.
+ * product rather than calculating it here. "pages" is the number of pages
+ * in the object under consideration (either an index or a table).
+ * "index_pages" is the amount to add to the total table space, which was
+ * computed for us by query_planner.
*
* Caller is expected to have ensured that tuples_fetched is greater than zero
* and rounded to integer (see clamp_row_est). The result will likewise be
@@ -383,17 +390,23 @@ cost_index(IndexPath *path, PlannerInfo *root,
*/
double
index_pages_fetched(double tuples_fetched, BlockNumber pages,
- BlockNumber other_pages)
+ double index_pages, PlannerInfo *root)
{
double pages_fetched;
+ double total_pages;
double T,
b;
/* T is # pages in table, but don't allow it to be zero */
T = (pages > 1) ? (double) pages : 1.0;
+ /* Compute number of pages assumed to be competing for cache space */
+ total_pages = root->total_table_pages + index_pages;
+ total_pages = Max(total_pages, 1.0);
+ Assert(T <= total_pages);
+
/* b is pro-rated share of effective_cache_size */
- b = (double) effective_cache_size * T / (T + (double) other_pages);
+ b = (double) effective_cache_size * T / total_pages;
/* force it positive and integral */
if (b <= 1.0)
b = 1.0;
@@ -431,6 +444,51 @@ index_pages_fetched(double tuples_fetched, BlockNumber pages,
}
/*
+ * get_indexpath_pages
+ * Determine the total size of the indexes used in a bitmap index path.
+ *
+ * Note: if the same index is used more than once in a bitmap tree, we will
+ * count it multiple times, which perhaps is the wrong thing ... but it's
+ * not completely clear, and detecting duplicates is difficult, so ignore it
+ * for now.
+ */
+static double
+get_indexpath_pages(Path *bitmapqual)
+{
+ double result = 0;
+ ListCell *l;
+
+ if (IsA(bitmapqual, BitmapAndPath))
+ {
+ BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
+
+ foreach(l, apath->bitmapquals)
+ {
+ result += get_indexpath_pages((Path *) lfirst(l));
+ }
+ }
+ else if (IsA(bitmapqual, BitmapOrPath))
+ {
+ BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
+
+ foreach(l, opath->bitmapquals)
+ {
+ result += get_indexpath_pages((Path *) lfirst(l));
+ }
+ }
+ else if (IsA(bitmapqual, IndexPath))
+ {
+ IndexPath *ipath = (IndexPath *) bitmapqual;
+
+ result = (double) ipath->indexinfo->pages;
+ }
+ else
+ elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
+
+ return result;
+}
+
+/*
* cost_bitmap_heap_scan
* Determines and returns the cost of scanning a relation using a bitmap
* index-then-heap plan.
@@ -494,7 +552,8 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
pages_fetched = index_pages_fetched(tuples_fetched * num_scans,
baserel->pages,
- 0 /* XXX total index size? */);
+ get_indexpath_pages(bitmapqual),
+ root);
pages_fetched /= num_scans;
}
else