5454 * Portions Copyright (c) 1994, Regents of the University of California
5555 *
5656 * IDENTIFICATION
57- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.165 2006/08/02 01:59:45 joe Exp $
57+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.166 2006/09/19 22:49:52 tgl Exp $
5858 *
5959 *-------------------------------------------------------------------------
6060 */
@@ -288,7 +288,8 @@ cost_index(IndexPath *path, PlannerInfo *root,
288288
289289pages_fetched = index_pages_fetched (tuples_fetched * num_scans ,
290290baserel -> pages ,
291- index -> pages );
291+ (double )index -> pages ,
292+ root );
292293
293294run_cost += (pages_fetched * random_page_cost ) /num_scans ;
294295}
@@ -300,7 +301,8 @@ cost_index(IndexPath *path, PlannerInfo *root,
300301 */
301302pages_fetched = index_pages_fetched (tuples_fetched ,
302303baserel -> pages ,
303- index -> pages );
304+ (double )index -> pages ,
305+ root );
304306
305307/* max_IO_cost is for the perfectly uncorrelated case (csquared=0) */
306308max_IO_cost = pages_fetched * random_page_cost ;
@@ -369,31 +371,42 @@ cost_index(IndexPath *path, PlannerInfo *root,
369371 *b = # buffer pages available (we include kernel space here)
370372 *
371373 * We assume that effective_cache_size is the total number of buffer pages
372- * available for both table and index, and pro-rate that space between the
373- * table and index. (Ideally other_pages should include all the other
374- * tables and indexes used by the query too; but we don't have a good way
375- * to get that number here.)
374+ * available for the whole query, and pro-rate that space across all the
375+ * tables in the query and the index currently under consideration. (This
376+ * ignores space needed for other indexes used by the query, but since we
377+ * don't know which indexes will get used, we can't estimate that very well;
378+ * and in any case counting all the tables may well be an overestimate, since
379+ * depending on the join plan not all the tables may be scanned concurrently.)
376380 *
377381 * The product Ns is the number of tuples fetched; we pass in that
378- * product rather than calculating it here.
382+ * product rather than calculating it here. "pages" is the number of pages
383+ * in the object under consideration (either an index or a table).
384+ * "index_pages" is the amount to add to the total table space, which was
385+ * computed for us by query_planner.
379386 *
380387 * Caller is expected to have ensured that tuples_fetched is greater than zero
381388 * and rounded to integer (see clamp_row_est). The result will likewise be
382389 * greater than zero and integral.
383390 */
384391double
385392index_pages_fetched (double tuples_fetched ,BlockNumber pages ,
386- BlockNumber other_pages )
393+ double index_pages , PlannerInfo * root )
387394{
388395double pages_fetched ;
396+ double total_pages ;
389397double T ,
390398b ;
391399
392400/* T is # pages in table, but don't allow it to be zero */
393401T = (pages > 1 ) ? (double )pages :1.0 ;
394402
403+ /* Compute number of pages assumed to be competing for cache space */
404+ total_pages = root -> total_table_pages + index_pages ;
405+ total_pages = Max (total_pages ,1.0 );
406+ Assert (T <=total_pages );
407+
395408/* b is pro-rated share of effective_cache_size */
396- b = (double )effective_cache_size * T /( T + ( double ) other_pages ) ;
409+ b = (double )effective_cache_size * T /total_pages ;
397410/* force it positive and integral */
398411if (b <=1.0 )
399412b = 1.0 ;
@@ -430,6 +443,51 @@ index_pages_fetched(double tuples_fetched, BlockNumber pages,
430443return pages_fetched ;
431444}
432445
446+ /*
447+ * get_indexpath_pages
448+ *Determine the total size of the indexes used in a bitmap index path.
449+ *
450+ * Note: if the same index is used more than once in a bitmap tree, we will
451+ * count it multiple times, which perhaps is the wrong thing ... but it's
452+ * not completely clear, and detecting duplicates is difficult, so ignore it
453+ * for now.
454+ */
455+ static double
456+ get_indexpath_pages (Path * bitmapqual )
457+ {
458+ double result = 0 ;
459+ ListCell * l ;
460+
461+ if (IsA (bitmapqual ,BitmapAndPath ))
462+ {
463+ BitmapAndPath * apath = (BitmapAndPath * )bitmapqual ;
464+
465+ foreach (l ,apath -> bitmapquals )
466+ {
467+ result += get_indexpath_pages ((Path * )lfirst (l ));
468+ }
469+ }
470+ else if (IsA (bitmapqual ,BitmapOrPath ))
471+ {
472+ BitmapOrPath * opath = (BitmapOrPath * )bitmapqual ;
473+
474+ foreach (l ,opath -> bitmapquals )
475+ {
476+ result += get_indexpath_pages ((Path * )lfirst (l ));
477+ }
478+ }
479+ else if (IsA (bitmapqual ,IndexPath ))
480+ {
481+ IndexPath * ipath = (IndexPath * )bitmapqual ;
482+
483+ result = (double )ipath -> indexinfo -> pages ;
484+ }
485+ else
486+ elog (ERROR ,"unrecognized node type: %d" ,nodeTag (bitmapqual ));
487+
488+ return result ;
489+ }
490+
433491/*
434492 * cost_bitmap_heap_scan
435493 * Determines and returns the cost of scanning a relation using a bitmap
@@ -494,7 +552,8 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
494552
495553pages_fetched = index_pages_fetched (tuples_fetched * num_scans ,
496554baserel -> pages ,
497- 0 /* XXX total index size? */ );
555+ get_indexpath_pages (bitmapqual ),
556+ root );
498557pages_fetched /=num_scans ;
499558}
500559else