@ -50,6 +50,17 @@
* so beware of division - by - zero . ) The LIMIT is applied as a top - level
* plan node .
*
* Each path stores the total number of disabled nodes that exist at or
* below that point in the plan tree . This is regarded as a component of
* the cost , and paths with fewer disabled nodes should be regarded as
* cheaper than those with more . Disabled nodes occur when the user sets
* a GUC like enable_seqscan = false . We can ' t necessarily respect such a
* setting in every part of the plan tree , but we want to respect in as many
* parts of the plan tree as possible . Simpler schemes like storing a Boolean
* here rather than a count fail to do that . We used to disable nodes by
* adding a large constant to the startup cost , but that distorted planning
* in other ways .
*
* For largely historical reasons , most of the routines in this module use
* the passed result Path only to store their results ( rows , startup_cost and
* total_cost ) into . All the input data they need is passed as separate
@ -301,9 +312,6 @@ cost_seqscan(Path *path, PlannerInfo *root,
else
path - > rows = baserel - > rows ;
if ( ! enable_seqscan )
startup_cost + = disable_cost ;
/* fetch estimated page cost for tablespace containing table */
get_tablespace_page_costs ( baserel - > reltablespace ,
NULL ,
@ -346,6 +354,7 @@ cost_seqscan(Path *path, PlannerInfo *root,
path - > rows = clamp_row_est ( path - > rows / parallel_divisor ) ;
}
path - > disabled_nodes = enable_seqscan ? 0 : 1 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + cpu_run_cost + disk_run_cost ;
}
@ -418,6 +427,7 @@ cost_samplescan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -456,6 +466,7 @@ cost_gather(GatherPath *path, PlannerInfo *root,
startup_cost + = parallel_setup_cost ;
run_cost + = parallel_tuple_cost * path - > path . rows ;
path - > path . disabled_nodes = path - > subpath - > disabled_nodes ;
path - > path . startup_cost = startup_cost ;
path - > path . total_cost = ( startup_cost + run_cost ) ;
}
@ -473,6 +484,7 @@ cost_gather(GatherPath *path, PlannerInfo *root,
void
cost_gather_merge ( GatherMergePath * path , PlannerInfo * root ,
RelOptInfo * rel , ParamPathInfo * param_info ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double * rows )
{
@ -490,9 +502,6 @@ cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
else
path - > path . rows = rel - > rows ;
if ( ! enable_gathermerge )
startup_cost + = disable_cost ;
/*
* Add one to the number of workers to account for the leader . This might
* be overgenerous since the leader will do less work than other workers
@ -523,6 +532,8 @@ cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
startup_cost + = parallel_setup_cost ;
run_cost + = parallel_tuple_cost * path - > path . rows * 1.05 ;
path - > path . disabled_nodes = input_disabled_nodes
+ ( enable_gathermerge ? 0 : 1 ) ;
path - > path . startup_cost = startup_cost + input_startup_cost ;
path - > path . total_cost = ( startup_cost + run_cost + input_total_cost ) ;
}
@ -603,9 +614,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count,
path - > indexclauses ) ;
}
if ( ! enable_indexscan )
startup_cost + = disable_cost ;
/* we don't need to check enable_indexonlyscan; indxpath.c does that */
path - > path . disabled_nodes = enable_indexscan ? 0 : 1 ;
/*
* Call index - access - method - specific code to estimate the processing cost
@ -1038,9 +1048,6 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
else
path - > rows = baserel - > rows ;
if ( ! enable_bitmapscan )
startup_cost + = disable_cost ;
pages_fetched = compute_bitmap_pages ( root , baserel , bitmapqual ,
loop_count , & indexTotalCost ,
& tuples_fetched ) ;
@ -1102,6 +1109,7 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = enable_bitmapscan ? 0 : 1 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1187,6 +1195,7 @@ cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root)
}
path - > bitmapselectivity = selec ;
path - > path . rows = 0 ; /* per above, not used */
path - > path . disabled_nodes = 0 ;
path - > path . startup_cost = totalCost ;
path - > path . total_cost = totalCost ;
}
@ -1261,6 +1270,7 @@ cost_tidscan(Path *path, PlannerInfo *root,
/* Should only be applied to base relations */
Assert ( baserel - > relid > 0 ) ;
Assert ( baserel - > rtekind = = RTE_RELATION ) ;
Assert ( tidquals ! = NIL ) ;
/* Mark the path with the correct row estimate */
if ( param_info )
@ -1275,6 +1285,14 @@ cost_tidscan(Path *path, PlannerInfo *root,
RestrictInfo * rinfo = lfirst_node ( RestrictInfo , l ) ;
Expr * qual = rinfo - > clause ;
/*
* We must use a TID scan for CurrentOfExpr ; in any other case , we
* should be generating a TID scan only if enable_tidscan = true . Also ,
* if CurrentOfExpr is the qual , there should be only one .
*/
Assert ( enable_tidscan | | IsA ( qual , CurrentOfExpr ) ) ;
Assert ( list_length ( tidquals ) = = 1 | | ! IsA ( qual , CurrentOfExpr ) ) ;
if ( IsA ( qual , ScalarArrayOpExpr ) )
{
/* Each element of the array yields 1 tuple */
@ -1322,6 +1340,12 @@ cost_tidscan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
/*
* There are assertions above verifying that we only reach this function
* either when enable_tidscan = true or when the TID scan is the only legal
* path , so it ' s safe to set disabled_nodes to zero here .
*/
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1414,6 +1438,9 @@ cost_tidrangescan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
/* we should not generate this path type when enable_tidscan=false */
Assert ( enable_tidscan ) ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1466,6 +1493,7 @@ cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root,
* SubqueryScan node , plus cpu_tuple_cost to account for selection and
* projection overhead .
*/
path - > path . disabled_nodes = path - > subpath - > disabled_nodes ;
path - > path . startup_cost = path - > subpath - > startup_cost ;
path - > path . total_cost = path - > subpath - > total_cost ;
@ -1556,6 +1584,7 @@ cost_functionscan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1612,6 +1641,7 @@ cost_tablefuncscan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1659,6 +1689,7 @@ cost_valuesscan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1706,6 +1737,7 @@ cost_ctescan(Path *path, PlannerInfo *root,
startup_cost + = path - > pathtarget - > cost . startup ;
run_cost + = path - > pathtarget - > cost . per_tuple * path - > rows ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1743,6 +1775,7 @@ cost_namedtuplestorescan(Path *path, PlannerInfo *root,
cpu_per_tuple + = cpu_tuple_cost + qpqual_cost . per_tuple ;
run_cost + = cpu_per_tuple * baserel - > tuples ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1777,6 +1810,7 @@ cost_resultscan(Path *path, PlannerInfo *root,
cpu_per_tuple = cpu_tuple_cost + qpqual_cost . per_tuple ;
run_cost + = cpu_per_tuple * baserel - > tuples ;
path - > disabled_nodes = 0 ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -1816,6 +1850,7 @@ cost_recursive_union(Path *runion, Path *nrterm, Path *rterm)
*/
total_cost + = cpu_tuple_cost * total_rows ;
runion - > disabled_nodes = nrterm - > disabled_nodes + rterm - > disabled_nodes ;
runion - > startup_cost = startup_cost ;
runion - > total_cost = total_cost ;
runion - > rows = total_rows ;
@ -1964,6 +1999,7 @@ cost_tuplesort(Cost *startup_cost, Cost *run_cost,
void
cost_incremental_sort ( Path * path ,
PlannerInfo * root , List * pathkeys , int presorted_keys ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double input_tuples , int width , Cost comparison_cost , int sort_mem ,
double limit_tuples )
@ -2083,6 +2119,11 @@ cost_incremental_sort(Path *path,
run_cost + = 2.0 * cpu_tuple_cost * input_groups ;
path - > rows = input_tuples ;
/* should not generate these paths when enable_incremental_sort=false */
Assert ( enable_incremental_sort ) ;
path - > disabled_nodes = input_disabled_nodes ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -2101,7 +2142,8 @@ cost_incremental_sort(Path *path,
*/
void
cost_sort ( Path * path , PlannerInfo * root ,
List * pathkeys , Cost input_cost , double tuples , int width ,
List * pathkeys , int input_disabled_nodes ,
Cost input_cost , double tuples , int width ,
Cost comparison_cost , int sort_mem ,
double limit_tuples )
@ -2114,12 +2156,10 @@ cost_sort(Path *path, PlannerInfo *root,
comparison_cost , sort_mem ,
limit_tuples ) ;
if ( ! enable_sort )
startup_cost + = disable_cost ;
startup_cost + = input_cost ;
path - > rows = tuples ;
path - > disabled_nodes = input_disabled_nodes + ( enable_sort ? 0 : 1 ) ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -2211,6 +2251,7 @@ cost_append(AppendPath *apath)
{
ListCell * l ;
apath - > path . disabled_nodes = 0 ;
apath - > path . startup_cost = 0 ;
apath - > path . total_cost = 0 ;
apath - > path . rows = 0 ;
@ -2232,12 +2273,16 @@ cost_append(AppendPath *apath)
*/
apath - > path . startup_cost = firstsubpath - > startup_cost ;
/* Compute rows and costs as sums of subplan rows and costs. */
/*
* Compute rows , number of disabled nodes , and total cost as sums
* of underlying subplan values .
*/
foreach ( l , apath - > subpaths )
{
Path * subpath = ( Path * ) lfirst ( l ) ;
apath - > path . rows + = subpath - > rows ;
apath - > path . disabled_nodes + = subpath - > disabled_nodes ;
apath - > path . total_cost + = subpath - > total_cost ;
}
}
@ -2277,6 +2322,7 @@ cost_append(AppendPath *apath)
cost_sort ( & sort_path ,
NULL , /* doesn't currently need root */
pathkeys ,
subpath - > disabled_nodes ,
subpath - > total_cost ,
subpath - > rows ,
subpath - > pathtarget - > width ,
@ -2287,6 +2333,7 @@ cost_append(AppendPath *apath)
}
apath - > path . rows + = subpath - > rows ;
apath - > path . disabled_nodes + = subpath - > disabled_nodes ;
apath - > path . startup_cost + = subpath - > startup_cost ;
apath - > path . total_cost + = subpath - > total_cost ;
}
@ -2335,6 +2382,7 @@ cost_append(AppendPath *apath)
apath - > path . total_cost + = subpath - > total_cost ;
}
apath - > path . disabled_nodes + = subpath - > disabled_nodes ;
apath - > path . rows = clamp_row_est ( apath - > path . rows ) ;
i + + ;
@ -2375,6 +2423,7 @@ cost_append(AppendPath *apath)
*
* ' pathkeys ' is a list of sort keys
* ' n_streams ' is the number of input streams
* ' input_disabled_nodes ' is the sum of the input streams ' disabled node counts
* ' input_startup_cost ' is the sum of the input streams ' startup costs
* ' input_total_cost ' is the sum of the input streams ' total costs
* ' tuples ' is the number of tuples in all the streams
@ -2382,6 +2431,7 @@ cost_append(AppendPath *apath)
void
cost_merge_append ( Path * path , PlannerInfo * root ,
List * pathkeys , int n_streams ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double tuples )
{
@ -2412,6 +2462,7 @@ cost_merge_append(Path *path, PlannerInfo *root,
*/
run_cost + = cpu_tuple_cost * APPEND_CPU_COST_MULTIPLIER * tuples ;
path - > disabled_nodes = input_disabled_nodes ;
path - > startup_cost = startup_cost + input_startup_cost ;
path - > total_cost = startup_cost + run_cost + input_total_cost ;
}
@ -2430,6 +2481,7 @@ cost_merge_append(Path *path, PlannerInfo *root,
*/
void
cost_material ( Path * path ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double tuples , int width )
{
@ -2467,6 +2519,7 @@ cost_material(Path *path,
run_cost + = seq_page_cost * npages ;
}
path - > disabled_nodes = input_disabled_nodes + ( enable_material ? 0 : 1 ) ;
path - > startup_cost = startup_cost ;
path - > total_cost = startup_cost + run_cost ;
}
@ -2630,6 +2683,7 @@ cost_agg(Path *path, PlannerInfo *root,
AggStrategy aggstrategy , const AggClauseCosts * aggcosts ,
int numGroupCols , double numGroups ,
List * quals ,
int disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double input_tuples , double input_width )
{
@ -2685,10 +2739,7 @@ cost_agg(Path *path, PlannerInfo *root,
startup_cost = input_startup_cost ;
total_cost = input_total_cost ;
if ( aggstrategy = = AGG_MIXED & & ! enable_hashagg )
{
startup_cost + = disable_cost ;
total_cost + = disable_cost ;
}
+ + disabled_nodes ;
/* calcs phrased this way to match HASHED case, see note above */
total_cost + = aggcosts - > transCost . startup ;
total_cost + = aggcosts - > transCost . per_tuple * input_tuples ;
@ -2703,7 +2754,7 @@ cost_agg(Path *path, PlannerInfo *root,
/* must be AGG_HASHED */
startup_cost = input_total_cost ;
if ( ! enable_hashagg )
startup_cost + = disable_cost ;
+ + disabled_nodes ;
startup_cost + = aggcosts - > transCost . startup ;
startup_cost + = aggcosts - > transCost . per_tuple * input_tuples ;
/* cost of computing hash value */
@ -2812,6 +2863,7 @@ cost_agg(Path *path, PlannerInfo *root,
}
path - > rows = output_tuples ;
path - > disabled_nodes = disabled_nodes ;
path - > startup_cost = startup_cost ;
path - > total_cost = total_cost ;
}
@ -3046,6 +3098,7 @@ get_windowclause_startup_tuples(PlannerInfo *root, WindowClause *wc,
void
cost_windowagg ( Path * path , PlannerInfo * root ,
List * windowFuncs , WindowClause * winclause ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double input_tuples )
{
@ -3111,6 +3164,7 @@ cost_windowagg(Path *path, PlannerInfo *root,
total_cost + = cpu_tuple_cost * input_tuples ;
path - > rows = input_tuples ;
path - > disabled_nodes = input_disabled_nodes ;
path - > startup_cost = startup_cost ;
path - > total_cost = total_cost ;
@ -3142,6 +3196,7 @@ void
cost_group ( Path * path , PlannerInfo * root ,
int numGroupCols , double numGroups ,
List * quals ,
int input_disabled_nodes ,
Cost input_startup_cost , Cost input_total_cost ,
double input_tuples )
{
@ -3180,6 +3235,7 @@ cost_group(Path *path, PlannerInfo *root,
}
path - > rows = output_tuples ;
path - > disabled_nodes = input_disabled_nodes ;
path - > startup_cost = startup_cost ;
path - > total_cost = total_cost ;
}
@ -3214,6 +3270,7 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
Path * outer_path , Path * inner_path ,
JoinPathExtraData * extra )
{
int disabled_nodes ;
Cost startup_cost = 0 ;
Cost run_cost = 0 ;
double outer_path_rows = outer_path - > rows ;
@ -3222,6 +3279,11 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
Cost inner_run_cost ;
Cost inner_rescan_run_cost ;
/* Count up disabled nodes. */
disabled_nodes = enable_nestloop ? 0 : 1 ;
disabled_nodes + = inner_path - > disabled_nodes ;
disabled_nodes + = outer_path - > disabled_nodes ;
/* estimate costs to rescan the inner relation */
cost_rescan ( root , inner_path ,
& inner_rescan_start_cost ,
@ -3269,6 +3331,7 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace,
/* CPU costs left for later */
/* Public result fields */
workspace - > disabled_nodes = disabled_nodes ;
workspace - > startup_cost = startup_cost ;
workspace - > total_cost = startup_cost + run_cost ;
/* Save private data for final_cost_nestloop */
@ -3298,6 +3361,9 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
QualCost restrict_qual_cost ;
double ntuples ;
/* Set the number of disabled nodes. */
path - > jpath . path . disabled_nodes = workspace - > disabled_nodes ;
/* Protect some assumptions below that rowcounts aren't zero */
if ( outer_path_rows < = 0 )
outer_path_rows = 1 ;
@ -3318,14 +3384,6 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
clamp_row_est ( path - > jpath . path . rows / parallel_divisor ) ;
}
/*
* We could include disable_cost in the preliminary estimate , but that
* would amount to optimizing for the case where the join method is
* disabled , which doesn ' t seem like the way to bet .
*/
if ( ! enable_nestloop )
startup_cost + = disable_cost ;
/* cost of inner-relation source data (we already dealt with outer rel) */
if ( path - > jpath . jointype = = JOIN_SEMI | | path - > jpath . jointype = = JOIN_ANTI | |
@ -3497,6 +3555,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
List * outersortkeys , List * innersortkeys ,
JoinPathExtraData * extra )
{
int disabled_nodes ;
Cost startup_cost = 0 ;
Cost run_cost = 0 ;
double outer_path_rows = outer_path - > rows ;
@ -3617,6 +3676,8 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
Assert ( outerstartsel < = outerendsel ) ;
Assert ( innerstartsel < = innerendsel ) ;
disabled_nodes = enable_mergejoin ? 0 : 1 ;
/* cost of source data */
if ( outersortkeys ) /* do we need to sort outer? */
@ -3624,12 +3685,14 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
cost_sort ( & sort_path ,
root ,
outersortkeys ,
outer_path - > disabled_nodes ,
outer_path - > total_cost ,
outer_path_rows ,
outer_path - > pathtarget - > width ,
0.0 ,
work_mem ,
- 1.0 ) ;
disabled_nodes + = sort_path . disabled_nodes ;
startup_cost + = sort_path . startup_cost ;
startup_cost + = ( sort_path . total_cost - sort_path . startup_cost )
* outerstartsel ;
@ -3638,6 +3701,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
}
else
{
disabled_nodes + = outer_path - > disabled_nodes ;
startup_cost + = outer_path - > startup_cost ;
startup_cost + = ( outer_path - > total_cost - outer_path - > startup_cost )
* outerstartsel ;
@ -3650,12 +3714,14 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
cost_sort ( & sort_path ,
root ,
innersortkeys ,
inner_path - > disabled_nodes ,
inner_path - > total_cost ,
inner_path_rows ,
inner_path - > pathtarget - > width ,
0.0 ,
work_mem ,
- 1.0 ) ;
disabled_nodes + = sort_path . disabled_nodes ;
startup_cost + = sort_path . startup_cost ;
startup_cost + = ( sort_path . total_cost - sort_path . startup_cost )
* innerstartsel ;
@ -3664,6 +3730,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
}
else
{
disabled_nodes + = inner_path - > disabled_nodes ;
startup_cost + = inner_path - > startup_cost ;
startup_cost + = ( inner_path - > total_cost - inner_path - > startup_cost )
* innerstartsel ;
@ -3682,6 +3749,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
/* CPU costs left for later */
/* Public result fields */
workspace - > disabled_nodes = disabled_nodes ;
workspace - > startup_cost = startup_cost ;
workspace - > total_cost = startup_cost + run_cost + inner_run_cost ;
/* Save private data for final_cost_mergejoin */
@ -3746,6 +3814,9 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
rescannedtuples ;
double rescanratio ;
/* Set the number of disabled nodes. */
path - > jpath . path . disabled_nodes = workspace - > disabled_nodes ;
/* Protect some assumptions below that rowcounts aren't zero */
if ( inner_path_rows < = 0 )
inner_path_rows = 1 ;
@ -3765,14 +3836,6 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
clamp_row_est ( path - > jpath . path . rows / parallel_divisor ) ;
}
/*
* We could include disable_cost in the preliminary estimate , but that
* would amount to optimizing for the case where the join method is
* disabled , which doesn ' t seem like the way to bet .
*/
if ( ! enable_mergejoin )
startup_cost + = disable_cost ;
/*
* Compute cost of the mergequals and qpquals ( other restriction clauses )
* separately .
@ -4056,6 +4119,7 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace,
JoinPathExtraData * extra ,
bool parallel_hash )
{
int disabled_nodes ;
Cost startup_cost = 0 ;
Cost run_cost = 0 ;
double outer_path_rows = outer_path - > rows ;
@ -4067,6 +4131,11 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace,
int num_skew_mcvs ;
size_t space_allowed ; /* unused */
/* Count up disabled nodes. */
disabled_nodes = enable_hashjoin ? 0 : 1 ;
disabled_nodes + = inner_path - > disabled_nodes ;
disabled_nodes + = outer_path - > disabled_nodes ;
/* cost of source data */
startup_cost + = outer_path - > startup_cost ;
run_cost + = outer_path - > total_cost - outer_path - > startup_cost ;
@ -4136,6 +4205,7 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace,
/* CPU costs left for later */
/* Public result fields */
workspace - > disabled_nodes = disabled_nodes ;
workspace - > startup_cost = startup_cost ;
workspace - > total_cost = startup_cost + run_cost ;
/* Save private data for final_cost_hashjoin */
@ -4180,6 +4250,9 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
Selectivity innermcvfreq ;
ListCell * hcl ;
/* Set the number of disabled nodes. */
path - > jpath . path . disabled_nodes = workspace - > disabled_nodes ;
/* Mark the path with the correct row estimate */
if ( path - > jpath . path . param_info )
path - > jpath . path . rows = path - > jpath . path . param_info - > ppi_rows ;
@ -4195,14 +4268,6 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
clamp_row_est ( path - > jpath . path . rows / parallel_divisor ) ;
}
/*
* We could include disable_cost in the preliminary estimate , but that
* would amount to optimizing for the case where the join method is
* disabled , which doesn ' t seem like the way to bet .
*/
if ( ! enable_hashjoin )
startup_cost + = disable_cost ;
/* mark the path with estimated # of batches */
path - > num_batches = numbatches ;