Skip to content

Commit d29d469

Browse files
committed
Show estimated number of groups for Incremental Sort in EXPLAIN
Incremental Sort's costs heavily depend on the estimated number of input groups with equal presorted key values. Overestimations can cause the planner to choose Incremental Sort over Sort when Sort would have been a better choice. Here, we add the planner's estimate to EXPLAIN to allow easier understanding of why Incremental Sort has been chosen. Author: Ilia Evdokimov <ilya.evdokimov@tantorlabs.com> Reviewed-by: Enrique Sánchez <enriqueesanchz@gmail.com> Reviewed-by: David Rowley <dgrowleyml@gmail.com> Reviewed-by: solai v <solai.cdac@gmail.com> Discussion: https://postgr.es/m/10682fef-3748-43f5-a932-7adcdd9bd2b8%40tantorlabs.com
1 parent 086f6f1 commit d29d469

8 files changed

Lines changed: 31 additions & 7 deletions

File tree

doc/src/sgml/perform.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ EXPLAIN SELECT * FROM tenk1 ORDER BY hundred, ten LIMIT 100;
325325
-&gt; Incremental Sort (cost=19.35..2033.39 rows=10000 width=244)
326326
Sort Key: hundred, ten
327327
Presorted Key: hundred
328+
Estimated Groups: 100
328329
-&gt; Index Scan using tenk1_hundred on tenk1 (cost=0.29..1574.20 rows=10000 width=244)
329330
</screen>
330331

src/backend/commands/explain.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3306,11 +3306,16 @@ static void
33063306
show_incremental_sort_info(IncrementalSortState *incrsortstate,
33073307
ExplainState *es)
33083308
{
3309+
IncrementalSort *plan = (IncrementalSort *) incrsortstate->ss.ps.plan;
33093310
IncrementalSortGroupInfo *fullsortGroupInfo;
33103311
IncrementalSortGroupInfo *prefixsortGroupInfo;
33113312

33123313
fullsortGroupInfo = &incrsortstate->incsort_info.fullsortGroupInfo;
33133314

3315+
if (es->costs)
3316+
ExplainPropertyFloat("Estimated Groups", NULL,
3317+
plan->numGroups, 0, es);
3318+
33143319
if (!es->analyze)
33153320
return;
33163321

src/backend/optimizer/path/costsize.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,14 +2049,18 @@ cost_tuplesort(Cost *startup_cost, Cost *run_cost,
20492049
* We estimate the number of groups into which the relation is divided by the
20502050
* leading pathkeys, and then calculate the cost of sorting a single group
20512051
* with tuplesort using cost_tuplesort().
2052+
*
2053+
* If num_groups is not NULL, *num_groups gets set to the estimated number of
2054+
* sort groups.
20522055
*/
20532056
void
20542057
cost_incremental_sort(Path *path,
20552058
PlannerInfo *root, List *pathkeys, int presorted_keys,
20562059
int input_disabled_nodes,
20572060
Cost input_startup_cost, Cost input_total_cost,
20582061
double input_tuples, int width, Cost comparison_cost, int sort_mem,
2059-
double limit_tuples)
2062+
double limit_tuples,
2063+
Cardinality *num_groups)
20602064
{
20612065
Cost startup_cost,
20622066
run_cost,
@@ -2184,6 +2188,10 @@ cost_incremental_sort(Path *path,
21842188

21852189
path->startup_cost = startup_cost;
21862190
path->total_cost = startup_cost + run_cost;
2191+
2192+
/* set output parameter values */
2193+
if (num_groups)
2194+
*num_groups = input_groups;
21872195
}
21882196

21892197
/*
@@ -2407,7 +2415,8 @@ cost_append(AppendPath *apath, PlannerInfo *root)
24072415
subpath->pathtarget->width,
24082416
0.0,
24092417
work_mem,
2410-
apath->limit_tuples);
2418+
apath->limit_tuples,
2419+
NULL);
24112420
}
24122421
else
24132422
{
@@ -3850,7 +3859,8 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
38503859
outer_path->pathtarget->width,
38513860
0.0,
38523861
work_mem,
3853-
-1.0);
3862+
-1.0,
3863+
NULL);
38543864
}
38553865
else
38563866
{

src/backend/optimizer/plan/createplan.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,7 @@ create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path,
20742074
best_path->nPresortedCols);
20752075

20762076
copy_generic_path_info(&plan->sort.plan, (Path *) best_path);
2077+
plan->numGroups = best_path->numGroups;
20772078

20782079
return plan;
20792080
}
@@ -5469,7 +5470,8 @@ label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan,
54695470
lefttree->plan_width,
54705471
0.0,
54715472
work_mem,
5472-
limit_tuples);
5473+
limit_tuples,
5474+
&plan->numGroups);
54735475
plan->sort.plan.startup_cost = sort_path.startup_cost;
54745476
plan->sort.plan.total_cost = sort_path.total_cost;
54755477
plan->sort.plan.plan_rows = lefttree->plan_rows;

src/backend/optimizer/util/pathnode.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,8 @@ create_merge_append_path(PlannerInfo *root,
16051605
subpath->pathtarget->width,
16061606
0.0,
16071607
work_mem,
1608-
pathnode->limit_tuples);
1608+
pathnode->limit_tuples,
1609+
NULL);
16091610
}
16101611
else
16111612
{
@@ -2883,7 +2884,8 @@ create_incremental_sort_path(PlannerInfo *root,
28832884
subpath->rows,
28842885
subpath->pathtarget->width,
28852886
0.0, /* XXX comparison_cost shouldn't be 0? */
2886-
work_mem, limit_tuples);
2887+
work_mem, limit_tuples,
2888+
&sort->numGroups);
28872889

28882890
sort->nPresortedCols = presorted_keys;
28892891

src/include/nodes/pathnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,7 @@ typedef struct IncrementalSortPath
25482548
{
25492549
SortPath spath;
25502550
int nPresortedCols; /* number of presorted columns */
2551+
Cardinality numGroups; /* estimated number of groups in input */
25512552
} IncrementalSortPath;
25522553

25532554
/*

src/include/nodes/plannodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,8 @@ typedef struct IncrementalSort
11711171
Sort sort;
11721172
/* number of presorted columns */
11731173
int nPresortedCols;
1174+
/* estimated number of groups in input */
1175+
Cardinality numGroups;
11741176
} IncrementalSort;
11751177

11761178
/* ---------------

src/include/optimizer/cost.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ extern void cost_incremental_sort(Path *path,
118118
int input_disabled_nodes,
119119
Cost input_startup_cost, Cost input_total_cost,
120120
double input_tuples, int width, Cost comparison_cost, int sort_mem,
121-
double limit_tuples);
121+
double limit_tuples,
122+
Cardinality *num_groups);
122123
extern void cost_append(AppendPath *apath, PlannerInfo *root);
123124
extern void cost_merge_append(Path *path, PlannerInfo *root,
124125
List *pathkeys, int n_streams,

0 commit comments

Comments
 (0)