4949 * Portions Copyright (c) 1994, Regents of the University of California
5050 *
5151 * IDENTIFICATION
52- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.143 2005/04/21 02:28:01 tgl Exp $
52+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.144 2005/04/21 19:18:12 tgl Exp $
5353 *
5454 *-------------------------------------------------------------------------
5555 */
@@ -94,6 +94,7 @@ Cost disable_cost = 100000000.0;
9494
9595bool enable_seqscan = true;
9696bool enable_indexscan = true;
97+ bool enable_bitmapscan = true;
9798bool enable_tidscan = true;
9899bool enable_sort = true;
99100bool enable_hashagg = true;
@@ -103,7 +104,7 @@ bool enable_hashjoin = true;
103104
104105
105106static bool cost_qual_eval_walker (Node * node , QualCost * total );
106- static Selectivity cost_bitmap_qual ( Node * bitmapqual , Cost * totalCost );
107+ static void cost_bitmap_tree_node ( Path * path , Cost * cost , Selectivity * selec );
107108static Selectivity approx_selectivity (Query * root , List * quals ,
108109 JoinType jointype );
109110static Selectivity join_in_selectivity (JoinPath * path , Query * root );
@@ -292,7 +293,7 @@ cost_index(IndexPath *path, Query *root,
292293 PointerGetDatum (& indexCorrelation ));
293294
294295 /*
295- * Save amcostestimate's results for possible use by cost_bitmap_scan .
296+ * Save amcostestimate's results for possible use in bitmap scan planning .
296297 * We don't bother to save indexStartupCost or indexCorrelation, because
297298 * a bitmap scan doesn't care about either.
298299 */
@@ -414,19 +415,19 @@ cost_index(IndexPath *path, Query *root,
414415}
415416
416417/*
417- * cost_bitmap_scan
418+ * cost_bitmap_heap_scan
418419 * Determines and returns the cost of scanning a relation using a bitmap
419420 * index-then-heap plan.
420421 *
421422 * 'root' is the query root
422423 * 'baserel' is the relation to be scanned
423- * 'bitmapqual' is an AND/OR tree of IndexPaths for the component scans
424+ * 'bitmapqual' is a tree of IndexPaths, BitmapAndPaths, and BitmapOrPaths
424425 * 'is_injoin' is T if we are considering using the scan as the inside
425426 * of a nestloop join (hence, some of the quals are join clauses)
426427 */
427428void
428- cost_bitmap_scan (Path * path , Query * root , RelOptInfo * baserel ,
429- Node * bitmapqual , bool is_injoin )
429+ cost_bitmap_heap_scan (Path * path , Query * root , RelOptInfo * baserel ,
430+ Path * bitmapqual , bool is_injoin )
430431{
431432 Cost startup_cost = 0 ;
432433 Cost run_cost = 0 ;
@@ -443,15 +444,14 @@ cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
443444 Assert (baserel -> relid > 0 );
444445 Assert (baserel -> rtekind == RTE_RELATION );
445446
446- if (!enable_indexscan ) /* XXX use a separate enable flag? */
447+ if (!enable_bitmapscan )
447448 startup_cost += disable_cost ;
448449
449450 /*
450- * Estimate total cost of obtaining the bitmap, as well as its total
451+ * Fetch total cost of obtaining the bitmap, as well as its total
451452 * selectivity.
452453 */
453- indexTotalCost = 0 ;
454- indexSelectivity = cost_bitmap_qual (bitmapqual , & indexTotalCost );
454+ cost_bitmap_tree_node (bitmapqual , & indexTotalCost , & indexSelectivity );
455455
456456 startup_cost += indexTotalCost ;
457457
@@ -497,82 +497,120 @@ cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
497497}
498498
499499/*
500- * cost_bitmap_qual
501- * Recursively examine the AND/OR/IndexPath tree for a bitmap scan
502- *
503- * Total execution costs are added to *totalCost (so caller must be sure
504- * to initialize that to zero). Estimated total selectivity of the bitmap
505- * is returned as the function result.
500+ * cost_bitmap_tree_node
501+ * Extract cost and selectivity from a bitmap tree node (index/and/or)
506502 */
507- static Selectivity
508- cost_bitmap_qual ( Node * bitmapqual , Cost * totalCost )
503+ static void
504+ cost_bitmap_tree_node ( Path * path , Cost * cost , Selectivity * selec )
509505{
510- Selectivity result ;
511- Selectivity subresult ;
512- ListCell * l ;
513-
514- if (and_clause (bitmapqual ))
506+ if (IsA (path , IndexPath ))
515507 {
516- /*
517- * We estimate AND selectivity on the assumption that the inputs
518- * are independent. This is probably often wrong, but we don't
519- * have the info to do better.
520- *
521- * The runtime cost of the BitmapAnd itself is estimated at 100x
522- * cpu_operator_cost for each tbm_intersect needed. Probably too
523- * small, definitely too simplistic?
524- *
525- * This must agree with make_bitmap_and in createplan.c.
526- */
527- result = 1.0 ;
528- foreach (l , ((BoolExpr * ) bitmapqual )-> args )
529- {
530- subresult = cost_bitmap_qual ((Node * ) lfirst (l ), totalCost );
531- result *= subresult ;
532- if (l != list_head (((BoolExpr * ) bitmapqual )-> args ))
533- * totalCost += 100.0 * cpu_operator_cost ;
534- }
508+ * cost = ((IndexPath * ) path )-> indextotalcost ;
509+ * selec = ((IndexPath * ) path )-> indexselectivity ;
535510 }
536- else if (or_clause ( bitmapqual ))
511+ else if (IsA ( path , BitmapAndPath ))
537512 {
538- /*
539- * We estimate OR selectivity on the assumption that the inputs
540- * are non-overlapping, since that's often the case in "x IN (list)"
541- * type situations. Of course, we clamp to 1.0 at the end.
542- *
543- * The runtime cost of the BitmapOr itself is estimated at 100x
544- * cpu_operator_cost for each tbm_union needed. Probably too
545- * small, definitely too simplistic? We are aware that the tbm_unions
546- * are optimized out when the inputs are BitmapIndexScans.
547- *
548- * This must agree with make_bitmap_or in createplan.c.
549- */
550- result = 0.0 ;
551- foreach (l , ((BoolExpr * ) bitmapqual )-> args )
552- {
553- subresult = cost_bitmap_qual ((Node * ) lfirst (l ), totalCost );
554- result += subresult ;
555- if (l != list_head (((BoolExpr * ) bitmapqual )-> args ) &&
556- !IsA ((Node * ) lfirst (l ), IndexPath ))
557- * totalCost += 100.0 * cpu_operator_cost ;
558- }
559- result = Min (result , 1.0 );
513+ * cost = path -> total_cost ;
514+ * selec = ((BitmapAndPath * ) path )-> bitmapselectivity ;
560515 }
561- else if (IsA (bitmapqual , IndexPath ))
516+ else if (IsA (path , BitmapOrPath ))
562517 {
563- IndexPath * ipath = (IndexPath * ) bitmapqual ;
564-
565- /* this must agree with create_bitmap_subplan in createplan.c */
566- * totalCost += ipath -> indextotalcost ;
567- result = ipath -> indexselectivity ;
518+ * cost = path -> total_cost ;
519+ * selec = ((BitmapOrPath * ) path )-> bitmapselectivity ;
568520 }
569521 else
522+ elog (ERROR , "unrecognized node type: %d" , nodeTag (path ));
523+ }
524+
525+ /*
526+ * cost_bitmap_and_node
527+ * Estimate the cost of a BitmapAnd node
528+ *
529+ * Note that this considers only the costs of index scanning and bitmap
530+ * creation, not the eventual heap access. In that sense the object isn't
531+ * truly a Path, but it has enough path-like properties (costs in particular)
532+ * to warrant treating it as one.
533+ */
534+ void
535+ cost_bitmap_and_node (BitmapAndPath * path , Query * root )
536+ {
537+ Cost totalCost ;
538+ Selectivity selec ;
539+ ListCell * l ;
540+
541+ /*
542+ * We estimate AND selectivity on the assumption that the inputs
543+ * are independent. This is probably often wrong, but we don't
544+ * have the info to do better.
545+ *
546+ * The runtime cost of the BitmapAnd itself is estimated at 100x
547+ * cpu_operator_cost for each tbm_intersect needed. Probably too
548+ * small, definitely too simplistic?
549+ */
550+ totalCost = 0.0 ;
551+ selec = 1.0 ;
552+ foreach (l , path -> bitmapquals )
570553 {
571- elog (ERROR , "unrecognized node type: %d" , nodeTag (bitmapqual ));
572- result = 0.0 ; /* keep compiler quiet */
554+ Path * subpath = (Path * ) lfirst (l );
555+ Cost subCost ;
556+ Selectivity subselec ;
557+
558+ cost_bitmap_tree_node (subpath , & subCost , & subselec );
559+
560+ selec *= subselec ;
561+
562+ totalCost += subCost ;
563+ if (l != list_head (path -> bitmapquals ))
564+ totalCost += 100.0 * cpu_operator_cost ;
573565 }
566+ path -> bitmapselectivity = selec ;
567+ path -> path .startup_cost = totalCost ;
568+ path -> path .total_cost = totalCost ;
569+ }
570+
571+ /*
572+ * cost_bitmap_or_node
573+ * Estimate the cost of a BitmapOr node
574+ *
575+ * See comments for cost_bitmap_and_node.
576+ */
577+ void
578+ cost_bitmap_or_node (BitmapOrPath * path , Query * root )
579+ {
580+ Cost totalCost ;
581+ Selectivity selec ;
582+ ListCell * l ;
583+
584+ /*
585+ * We estimate OR selectivity on the assumption that the inputs
586+ * are non-overlapping, since that's often the case in "x IN (list)"
587+ * type situations. Of course, we clamp to 1.0 at the end.
588+ *
589+ * The runtime cost of the BitmapOr itself is estimated at 100x
590+ * cpu_operator_cost for each tbm_union needed. Probably too
591+ * small, definitely too simplistic? We are aware that the tbm_unions
592+ * are optimized out when the inputs are BitmapIndexScans.
593+ */
594+ totalCost = 0.0 ;
595+ selec = 0.0 ;
596+ foreach (l , path -> bitmapquals )
597+ {
598+ Path * subpath = (Path * ) lfirst (l );
599+ Cost subCost ;
600+ Selectivity subselec ;
574601
575- return result ;
602+ cost_bitmap_tree_node (subpath , & subCost , & subselec );
603+
604+ selec += subselec ;
605+
606+ totalCost += subCost ;
607+ if (l != list_head (path -> bitmapquals ) &&
608+ !IsA (subpath , IndexPath ))
609+ totalCost += 100.0 * cpu_operator_cost ;
610+ }
611+ path -> bitmapselectivity = Min (selec , 1.0 );
612+ path -> path .startup_cost = totalCost ;
613+ path -> path .total_cost = totalCost ;
576614}
577615
578616/*
0 commit comments