@ -49,7 +49,7 @@
* Portions Copyright ( c ) 1994 , Regents of the University of California
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / optimizer / path / costsize . c , v 1.143 2005 / 04 / 21 02 : 28 : 01 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / optimizer / path / costsize . c , v 1.144 2005 / 04 / 21 19 : 18 : 12 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -94,6 +94,7 @@ Cost disable_cost = 100000000.0;
bool enable_seqscan = true ;
bool enable_seqscan = true ;
bool enable_indexscan = true ;
bool enable_indexscan = true ;
bool enable_bitmapscan = true ;
bool enable_tidscan = true ;
bool enable_tidscan = true ;
bool enable_sort = true ;
bool enable_sort = true ;
bool enable_hashagg = true ;
bool enable_hashagg = true ;
@ -103,7 +104,7 @@ bool enable_hashjoin = true;
static bool cost_qual_eval_walker ( Node * node , QualCost * total ) ;
static bool cost_qual_eval_walker ( Node * node , QualCost * total ) ;
static Selectivity cost_bitmap_qual ( Node * bitmapqual , Cost * totalCost ) ;
static void cost_bitmap_tree_node ( Path * path , Cost * cost , Selectivity * selec ) ;
static Selectivity approx_selectivity ( Query * root , List * quals ,
static Selectivity approx_selectivity ( Query * root , List * quals ,
JoinType jointype ) ;
JoinType jointype ) ;
static Selectivity join_in_selectivity ( JoinPath * path , Query * root ) ;
static Selectivity join_in_selectivity ( JoinPath * path , Query * root ) ;
@ -292,7 +293,7 @@ cost_index(IndexPath *path, Query *root,
PointerGetDatum ( & indexCorrelation ) ) ;
PointerGetDatum ( & indexCorrelation ) ) ;
/*
/*
* Save amcostestimate ' s results for possible use by cost_bitmap_scan .
* Save amcostestimate ' s results for possible use in bitmap scan planning .
* We don ' t bother to save indexStartupCost or indexCorrelation , because
* We don ' t bother to save indexStartupCost or indexCorrelation , because
* a bitmap scan doesn ' t care about either .
* a bitmap scan doesn ' t care about either .
*/
*/
@ -414,19 +415,19 @@ cost_index(IndexPath *path, Query *root,
}
}
/*
/*
* cost_bitmap_scan
* cost_bitmap_heap_ scan
* Determines and returns the cost of scanning a relation using a bitmap
* Determines and returns the cost of scanning a relation using a bitmap
* index - then - heap plan .
* index - then - heap plan .
*
*
* ' root ' is the query root
* ' root ' is the query root
* ' baserel ' is the relation to be scanned
* ' baserel ' is the relation to be scanned
* ' bitmapqual ' is an AND / OR tree of IndexPaths for the component scan s
* ' bitmapqual ' is a tree of IndexPaths , BitmapAndPaths , and BitmapOrPath s
* ' is_injoin ' is T if we are considering using the scan as the inside
* ' is_injoin ' is T if we are considering using the scan as the inside
* of a nestloop join ( hence , some of the quals are join clauses )
* of a nestloop join ( hence , some of the quals are join clauses )
*/
*/
void
void
cost_bitmap_scan ( Path * path , Query * root , RelOptInfo * baserel ,
cost_bitmap_heap_ scan ( Path * path , Query * root , RelOptInfo * baserel ,
Node * bitmapqual , bool is_injoin )
Path * bitmapqual , bool is_injoin )
{
{
Cost startup_cost = 0 ;
Cost startup_cost = 0 ;
Cost run_cost = 0 ;
Cost run_cost = 0 ;
@ -443,15 +444,14 @@ cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
Assert ( baserel - > relid > 0 ) ;
Assert ( baserel - > relid > 0 ) ;
Assert ( baserel - > rtekind = = RTE_RELATION ) ;
Assert ( baserel - > rtekind = = RTE_RELATION ) ;
if ( ! enable_indexscan ) /* XXX use a separate enable flag? */
if ( ! enable_bitmapscan )
startup_cost + = disable_cost ;
startup_cost + = disable_cost ;
/*
/*
* Estimate total cost of obtaining the bitmap , as well as its total
* Fetch total cost of obtaining the bitmap , as well as its total
* selectivity .
* selectivity .
*/
*/
indexTotalCost = 0 ;
cost_bitmap_tree_node ( bitmapqual , & indexTotalCost , & indexSelectivity ) ;
indexSelectivity = cost_bitmap_qual ( bitmapqual , & indexTotalCost ) ;
startup_cost + = indexTotalCost ;
startup_cost + = indexTotalCost ;
@ -497,82 +497,120 @@ cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
}
}
/*
/*
* cost_bitmap_qual
* cost_bitmap_tree_node
* Recursively examine the AND / OR / IndexPath tree for a bitmap scan
* Extract cost and selectivity from a bitmap tree node ( index / and / or )
*
* Total execution costs are added to * totalCost ( so caller must be sure
* to initialize that to zero ) . Estimated total selectivity of the bitmap
* is returned as the function result .
*/
*/
static Selectivity
static void
cost_bitmap_qual ( Node * bitmapqual , Cost * totalCost )
cost_bitmap_tree_node ( Path * path , Cost * cost , Selectivity * selec )
{
{
Selectivity result ;
if ( IsA ( path , IndexPath ) )
Selectivity subresult ;
ListCell * l ;
if ( and_clause ( bitmapqual ) )
{
{
/*
* cost = ( ( IndexPath * ) path ) - > indextotalcost ;
* We estimate AND selectivity on the assumption that the inputs
* selec = ( ( IndexPath * ) path ) - > indexselectivity ;
* are independent . This is probably often wrong , but we don ' t
* have the info to do better .
*
* The runtime cost of the BitmapAnd itself is estimated at 100 x
* cpu_operator_cost for each tbm_intersect needed . Probably too
* small , definitely too simplistic ?
*
* This must agree with make_bitmap_and in createplan . c .
*/
result = 1.0 ;
foreach ( l , ( ( BoolExpr * ) bitmapqual ) - > args )
{
subresult = cost_bitmap_qual ( ( Node * ) lfirst ( l ) , totalCost ) ;
result * = subresult ;
if ( l ! = list_head ( ( ( BoolExpr * ) bitmapqual ) - > args ) )
* totalCost + = 100.0 * cpu_operator_cost ;
}
}
}
else if ( or_clause ( bitmapqual ) )
else if ( IsA ( path , BitmapAndPath ) )
{
{
/*
* cost = path - > total_cost ;
* We estimate OR selectivity on the assumption that the inputs
* selec = ( ( BitmapAndPath * ) path ) - > bitmapselectivity ;
* are non - overlapping , since that ' s often the case in " x IN (list) "
* type situations . Of course , we clamp to 1.0 at the end .
*
* The runtime cost of the BitmapOr itself is estimated at 100 x
* cpu_operator_cost for each tbm_union needed . Probably too
* small , definitely too simplistic ? We are aware that the tbm_unions
* are optimized out when the inputs are BitmapIndexScans .
*
* This must agree with make_bitmap_or in createplan . c .
*/
result = 0.0 ;
foreach ( l , ( ( BoolExpr * ) bitmapqual ) - > args )
{
subresult = cost_bitmap_qual ( ( Node * ) lfirst ( l ) , totalCost ) ;
result + = subresult ;
if ( l ! = list_head ( ( ( BoolExpr * ) bitmapqual ) - > args ) & &
! IsA ( ( Node * ) lfirst ( l ) , IndexPath ) )
* totalCost + = 100.0 * cpu_operator_cost ;
}
result = Min ( result , 1.0 ) ;
}
}
else if ( IsA ( bitmapqual , Index Path) )
else if ( IsA ( path , BitmapOrPath ) )
{
{
IndexPath * ipath = ( IndexPath * ) bitmapqual ;
* cost = path - > total_cost ;
* selec = ( ( BitmapOrPath * ) path ) - > bitmapselectivity ;
/* this must agree with create_bitmap_subplan in createplan.c */
* totalCost + = ipath - > indextotalcost ;
result = ipath - > indexselectivity ;
}
}
else
else
elog ( ERROR , " unrecognized node type: %d " , nodeTag ( path ) ) ;
}
/*
* cost_bitmap_and_node
* Estimate the cost of a BitmapAnd node
*
* Note that this considers only the costs of index scanning and bitmap
* creation , not the eventual heap access . In that sense the object isn ' t
* truly a Path , but it has enough path - like properties ( costs in particular )
* to warrant treating it as one .
*/
void
cost_bitmap_and_node ( BitmapAndPath * path , Query * root )
{
Cost totalCost ;
Selectivity selec ;
ListCell * l ;
/*
* We estimate AND selectivity on the assumption that the inputs
* are independent . This is probably often wrong , but we don ' t
* have the info to do better .
*
* The runtime cost of the BitmapAnd itself is estimated at 100 x
* cpu_operator_cost for each tbm_intersect needed . Probably too
* small , definitely too simplistic ?
*/
totalCost = 0.0 ;
selec = 1.0 ;
foreach ( l , path - > bitmapquals )
{
{
elog ( ERROR , " unrecognized node type: %d " , nodeTag ( bitmapqual ) ) ;
Path * subpath = ( Path * ) lfirst ( l ) ;
result = 0.0 ; /* keep compiler quiet */
Cost subCost ;
Selectivity subselec ;
cost_bitmap_tree_node ( subpath , & subCost , & subselec ) ;
selec * = subselec ;
totalCost + = subCost ;
if ( l ! = list_head ( path - > bitmapquals ) )
totalCost + = 100.0 * cpu_operator_cost ;
}
}
path - > bitmapselectivity = selec ;
path - > path . startup_cost = totalCost ;
path - > path . total_cost = totalCost ;
}
/*
* cost_bitmap_or_node
* Estimate the cost of a BitmapOr node
*
* See comments for cost_bitmap_and_node .
*/
void
cost_bitmap_or_node ( BitmapOrPath * path , Query * root )
{
Cost totalCost ;
Selectivity selec ;
ListCell * l ;
/*
* We estimate OR selectivity on the assumption that the inputs
* are non - overlapping , since that ' s often the case in " x IN (list) "
* type situations . Of course , we clamp to 1.0 at the end .
*
* The runtime cost of the BitmapOr itself is estimated at 100 x
* cpu_operator_cost for each tbm_union needed . Probably too
* small , definitely too simplistic ? We are aware that the tbm_unions
* are optimized out when the inputs are BitmapIndexScans .
*/
totalCost = 0.0 ;
selec = 0.0 ;
foreach ( l , path - > bitmapquals )
{
Path * subpath = ( Path * ) lfirst ( l ) ;
Cost subCost ;
Selectivity subselec ;
return result ;
cost_bitmap_tree_node ( subpath , & subCost , & subselec ) ;
selec + = subselec ;
totalCost + = subCost ;
if ( l ! = list_head ( path - > bitmapquals ) & &
! IsA ( subpath , IndexPath ) )
totalCost + = 100.0 * cpu_operator_cost ;
}
path - > bitmapselectivity = Min ( selec , 1.0 ) ;
path - > path . startup_cost = totalCost ;
path - > path . total_cost = totalCost ;
}
}
/*
/*