Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e222534

Browse files
committed
Treat number of disabled nodes in a path as a separate cost metric.
Previously, when a path type was disabled by e.g. enable_seqscan=false, we either avoided generating that path type in the first place, or more commonly, we added a large constant, called disable_cost, to the estimated startup cost of that path. This latter approach can distort planning. For instance, an extremely expensive non-disabled path could seem to be worse than a disabled path, especially if the full cost of that path node need not be paid (e.g. due to a Limit). Or, as in the regression test whose expected output changes with this commit, the addition of disable_cost can make two paths that would normally be distinguishible in cost seem to have fuzzily the same cost. To fix that, we now count the number of disabled path nodes and consider that a high-order component of both the startup cost and the total cost. Hence, the path list is now sorted by disabled_nodes and then by total_cost, instead of just by the latter, and likewise for the partial path list. It is important that this number is a count and not simply a Boolean; else, as soon as we're unable to respect disabled path types in all portions of the path, we stop trying to avoid them where we can. Because the path list is now sorted by the number of disabled nodes, the join prechecks must compute the count of disabled nodes during the initial cost phase instead of postponing it to final cost time. Counts of disabled nodes do not cross subquery levels; at present, there is no reason for them to do so, since the we do not postpone path selection across subquery boundaries (see make_subplan). Reviewed by Andres Freund, Heikki Linnakangas, and David Rowley. Discussion: http://postgr.es/m/CA+TgmoZ_+MS+o6NeGK2xyBv-xM+w1AfFVuHE4f_aq6ekHv7YSQ@mail.gmail.com
1 parent 2b03cfe commit e222534

File tree

15 files changed

+357
-127
lines changed

15 files changed

+357
-127
lines changed

contrib/file_fdw/file_fdw.c

+1
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ fileGetForeignPaths(PlannerInfo *root,
576576
create_foreignscan_path(root, baserel,
577577
NULL, /* default pathtarget */
578578
baserel->rows,
579+
0,
579580
startup_cost,
580581
total_cost,
581582
NIL, /* no pathkeys */

contrib/postgres_fdw/postgres_fdw.c

+39-7
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ static void estimate_path_cost_size(PlannerInfo *root,
430430
List *pathkeys,
431431
PgFdwPathExtraData *fpextra,
432432
double *p_rows, int *p_width,
433+
int *p_disabled_nodes,
433434
Cost *p_startup_cost, Cost *p_total_cost);
434435
static void get_remote_estimate(const char *sql,
435436
PGconn *conn,
@@ -442,6 +443,7 @@ static void adjust_foreign_grouping_path_cost(PlannerInfo *root,
442443
double retrieved_rows,
443444
double width,
444445
double limit_tuples,
446+
int *disabled_nodes,
445447
Cost *p_startup_cost,
446448
Cost *p_run_cost);
447449
static bool ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel,
@@ -735,6 +737,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
735737
*/
736738
estimate_path_cost_size(root, baserel, NIL, NIL, NULL,
737739
&fpinfo->rows, &fpinfo->width,
740+
&fpinfo->disabled_nodes,
738741
&fpinfo->startup_cost, &fpinfo->total_cost);
739742

740743
/* Report estimated baserel size to planner. */
@@ -765,6 +768,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
765768
/* Fill in basically-bogus cost estimates for use later. */
766769
estimate_path_cost_size(root, baserel, NIL, NIL, NULL,
767770
&fpinfo->rows, &fpinfo->width,
771+
&fpinfo->disabled_nodes,
768772
&fpinfo->startup_cost, &fpinfo->total_cost);
769773
}
770774

@@ -1030,6 +1034,7 @@ postgresGetForeignPaths(PlannerInfo *root,
10301034
path = create_foreignscan_path(root, baserel,
10311035
NULL, /* default pathtarget */
10321036
fpinfo->rows,
1037+
fpinfo->disabled_nodes,
10331038
fpinfo->startup_cost,
10341039
fpinfo->total_cost,
10351040
NIL, /* no pathkeys */
@@ -1184,13 +1189,14 @@ postgresGetForeignPaths(PlannerInfo *root,
11841189
ParamPathInfo *param_info = (ParamPathInfo *) lfirst(lc);
11851190
double rows;
11861191
int width;
1192+
int disabled_nodes;
11871193
Cost startup_cost;
11881194
Cost total_cost;
11891195

11901196
/* Get a cost estimate from the remote */
11911197
estimate_path_cost_size(root, baserel,
11921198
param_info->ppi_clauses, NIL, NULL,
1193-
&rows, &width,
1199+
&rows, &width, &disabled_nodes,
11941200
&startup_cost, &total_cost);
11951201

11961202
/*
@@ -1203,6 +1209,7 @@ postgresGetForeignPaths(PlannerInfo *root,
12031209
path = create_foreignscan_path(root, baserel,
12041210
NULL, /* default pathtarget */
12051211
rows,
1212+
disabled_nodes,
12061213
startup_cost,
12071214
total_cost,
12081215
NIL, /* no pathkeys */
@@ -3079,7 +3086,7 @@ postgresExecForeignTruncate(List *rels,
30793086
* final sort and the LIMIT restriction.
30803087
*
30813088
* The function returns the cost and size estimates in p_rows, p_width,
3082-
* p_startup_cost and p_total_cost variables.
3089+
* p_disabled_nodes, p_startup_cost and p_total_cost variables.
30833090
*/
30843091
static void
30853092
estimate_path_cost_size(PlannerInfo *root,
@@ -3088,12 +3095,14 @@ estimate_path_cost_size(PlannerInfo *root,
30883095
List *pathkeys,
30893096
PgFdwPathExtraData *fpextra,
30903097
double *p_rows, int *p_width,
3098+
int *p_disabled_nodes,
30913099
Cost *p_startup_cost, Cost *p_total_cost)
30923100
{
30933101
PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
30943102
double rows;
30953103
double retrieved_rows;
30963104
int width;
3105+
int disabled_nodes = 0;
30973106
Cost startup_cost;
30983107
Cost total_cost;
30993108

@@ -3483,6 +3492,7 @@ estimate_path_cost_size(PlannerInfo *root,
34833492
adjust_foreign_grouping_path_cost(root, pathkeys,
34843493
retrieved_rows, width,
34853494
fpextra->limit_tuples,
3495+
&disabled_nodes,
34863496
&startup_cost, &run_cost);
34873497
}
34883498
else
@@ -3577,6 +3587,7 @@ estimate_path_cost_size(PlannerInfo *root,
35773587
/* Return results. */
35783588
*p_rows = rows;
35793589
*p_width = width;
3590+
*p_disabled_nodes = disabled_nodes;
35803591
*p_startup_cost = startup_cost;
35813592
*p_total_cost = total_cost;
35823593
}
@@ -3637,6 +3648,7 @@ adjust_foreign_grouping_path_cost(PlannerInfo *root,
36373648
double retrieved_rows,
36383649
double width,
36393650
double limit_tuples,
3651+
int *p_disabled_nodes,
36403652
Cost *p_startup_cost,
36413653
Cost *p_run_cost)
36423654
{
@@ -3656,6 +3668,7 @@ adjust_foreign_grouping_path_cost(PlannerInfo *root,
36563668
cost_sort(&sort_path,
36573669
root,
36583670
pathkeys,
3671+
0,
36593672
*p_startup_cost + *p_run_cost,
36603673
retrieved_rows,
36613674
width,
@@ -6147,13 +6160,15 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
61476160
{
61486161
double rows;
61496162
int width;
6163+
int disabled_nodes;
61506164
Cost startup_cost;
61516165
Cost total_cost;
61526166
List *useful_pathkeys = lfirst(lc);
61536167
Path *sorted_epq_path;
61546168

61556169
estimate_path_cost_size(root, rel, NIL, useful_pathkeys, NULL,
6156-
&rows, &width, &startup_cost, &total_cost);
6170+
&rows, &width, &disabled_nodes,
6171+
&startup_cost, &total_cost);
61576172

61586173
/*
61596174
* The EPQ path must be at least as well sorted as the path itself, in
@@ -6175,6 +6190,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
61756190
create_foreignscan_path(root, rel,
61766191
NULL,
61776192
rows,
6193+
disabled_nodes,
61786194
startup_cost,
61796195
total_cost,
61806196
useful_pathkeys,
@@ -6188,6 +6204,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
61886204
create_foreign_join_path(root, rel,
61896205
NULL,
61906206
rows,
6207+
disabled_nodes,
61916208
startup_cost,
61926209
total_cost,
61936210
useful_pathkeys,
@@ -6335,6 +6352,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
63356352
ForeignPath *joinpath;
63366353
double rows;
63376354
int width;
6355+
int disabled_nodes;
63386356
Cost startup_cost;
63396357
Cost total_cost;
63406358
Path *epq_path; /* Path to create plan to be executed when
@@ -6424,12 +6442,14 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
64246442

64256443
/* Estimate costs for bare join relation */
64266444
estimate_path_cost_size(root, joinrel, NIL, NIL, NULL,
6427-
&rows, &width, &startup_cost, &total_cost);
6445+
&rows, &width, &disabled_nodes,
6446+
&startup_cost, &total_cost);
64286447
/* Now update this information in the joinrel */
64296448
joinrel->rows = rows;
64306449
joinrel->reltarget->width = width;
64316450
fpinfo->rows = rows;
64326451
fpinfo->width = width;
6452+
fpinfo->disabled_nodes = disabled_nodes;
64336453
fpinfo->startup_cost = startup_cost;
64346454
fpinfo->total_cost = total_cost;
64356455

@@ -6441,6 +6461,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
64416461
joinrel,
64426462
NULL, /* default pathtarget */
64436463
rows,
6464+
disabled_nodes,
64446465
startup_cost,
64456466
total_cost,
64466467
NIL, /* no pathkeys */
@@ -6768,6 +6789,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
67686789
ForeignPath *grouppath;
67696790
double rows;
67706791
int width;
6792+
int disabled_nodes;
67716793
Cost startup_cost;
67726794
Cost total_cost;
67736795

@@ -6818,11 +6840,13 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
68186840

68196841
/* Estimate the cost of push down */
68206842
estimate_path_cost_size(root, grouped_rel, NIL, NIL, NULL,
6821-
&rows, &width, &startup_cost, &total_cost);
6843+
&rows, &width, &disabled_nodes,
6844+
&startup_cost, &total_cost);
68226845

68236846
/* Now update this information in the fpinfo */
68246847
fpinfo->rows = rows;
68256848
fpinfo->width = width;
6849+
fpinfo->disabled_nodes = disabled_nodes;
68266850
fpinfo->startup_cost = startup_cost;
68276851
fpinfo->total_cost = total_cost;
68286852

@@ -6831,6 +6855,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
68316855
grouped_rel,
68326856
grouped_rel->reltarget,
68336857
rows,
6858+
disabled_nodes,
68346859
startup_cost,
68356860
total_cost,
68366861
NIL, /* no pathkeys */
@@ -6859,6 +6884,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
68596884
PgFdwPathExtraData *fpextra;
68606885
double rows;
68616886
int width;
6887+
int disabled_nodes;
68626888
Cost startup_cost;
68636889
Cost total_cost;
68646890
List *fdw_private;
@@ -6952,7 +6978,8 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
69526978

69536979
/* Estimate the costs of performing the final sort remotely */
69546980
estimate_path_cost_size(root, input_rel, NIL, root->sort_pathkeys, fpextra,
6955-
&rows, &width, &startup_cost, &total_cost);
6981+
&rows, &width, &disabled_nodes,
6982+
&startup_cost, &total_cost);
69566983

69576984
/*
69586985
* Build the fdw_private list that will be used by postgresGetForeignPlan.
@@ -6965,6 +6992,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
69656992
input_rel,
69666993
root->upper_targets[UPPERREL_ORDERED],
69676994
rows,
6995+
disabled_nodes,
69686996
startup_cost,
69696997
total_cost,
69706998
root->sort_pathkeys,
@@ -6998,6 +7026,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
69987026
bool save_use_remote_estimate = false;
69997027
double rows;
70007028
int width;
7029+
int disabled_nodes;
70017030
Cost startup_cost;
70027031
Cost total_cost;
70037032
List *fdw_private;
@@ -7082,6 +7111,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
70827111
path->parent,
70837112
path->pathtarget,
70847113
path->rows,
7114+
path->disabled_nodes,
70857115
path->startup_cost,
70867116
path->total_cost,
70877117
path->pathkeys,
@@ -7199,7 +7229,8 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
71997229
ifpinfo->use_remote_estimate = false;
72007230
}
72017231
estimate_path_cost_size(root, input_rel, NIL, pathkeys, fpextra,
7202-
&rows, &width, &startup_cost, &total_cost);
7232+
&rows, &width, &disabled_nodes,
7233+
&startup_cost, &total_cost);
72037234
if (!fpextra->has_final_sort)
72047235
ifpinfo->use_remote_estimate = save_use_remote_estimate;
72057236

@@ -7218,6 +7249,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
72187249
input_rel,
72197250
root->upper_targets[UPPERREL_FINAL],
72207251
rows,
7252+
disabled_nodes,
72217253
startup_cost,
72227254
total_cost,
72237255
pathkeys,

contrib/postgres_fdw/postgres_fdw.h

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ typedef struct PgFdwRelationInfo
6262
/* Estimated size and cost for a scan, join, or grouping/aggregation. */
6363
double rows;
6464
int width;
65+
int disabled_nodes;
6566
Cost startup_cost;
6667
Cost total_cost;
6768

0 commit comments

Comments
 (0)