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/2102:28:01 tgl Exp $
52+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.144 2005/04/2119:18:12 tgl Exp $
5353 *
5454 *-------------------------------------------------------------------------
5555 */
@@ -94,6 +94,7 @@ Costdisable_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 @@ boolenable_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 ,
108109JoinType jointype );
109110static Selectivity join_in_selectivity (JoinPath * path ,Query * root );
@@ -292,7 +293,7 @@ cost_index(IndexPath *path, Query *root,
292293PointerGetDatum (& indexCorrelation ));
293294
294295/*
295- * Save amcostestimate's results for possible useby cost_bitmap_scan .
296+ * Save amcostestimate's results for possible usein 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' isan AND/OR tree of IndexPaths for the component scans
424+ * 'bitmapqual' isa 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{
431432Cost startup_cost = 0 ;
432433Cost run_cost = 0 ;
@@ -443,15 +444,14 @@ cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
443444Assert (baserel -> relid > 0 );
444445Assert (baserel -> rtekind == RTE_RELATION );
445446
446- if (!enable_indexscan ) /* XXX use a separate enable flag? */
447+ if (!enable_bitmapscan )
447448startup_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
456456startup_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}
569521else
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/*