Skip to content

Commit 91224ee

Browse files
committed
Partial sort
1 parent 8eea52e commit 91224ee

File tree

4 files changed

+85
-15
lines changed

4 files changed

+85
-15
lines changed

src/backend/optimizer/path/pathkeys.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,40 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
430430
return matched_path;
431431
}
432432

433+
Path *
434+
get_cheapest_partial_path_for_pathkeys(List *paths,
435+
List *pathkeys,
436+
Relids required_outer,
437+
double fraction)
438+
{
439+
Path *matched_path = NULL;
440+
ListCell *l;
441+
int best_prefix_len = 0;
442+
foreach(l, paths)
443+
{
444+
Path *path = (Path *) lfirst(l);
445+
int prefix_len = pathkeys_get_prefix(pathkeys, path->pathkeys);
446+
if (prefix_len < best_prefix_len || path->pathtype != T_IndexOnlyScan) {
447+
continue;
448+
}
449+
/*
450+
* Since cost comparison is a lot cheaper than pathkey comparison, do
451+
* that first. (XXX is that still true?)
452+
*/
453+
if (matched_path != NULL &&
454+
compare_fractional_path_costs(matched_path, path, fraction) <= 0)
455+
continue;
456+
457+
if (prefix_len != 0
458+
&& bms_is_subset(PATH_REQ_OUTER(path), required_outer))
459+
{
460+
matched_path = path;
461+
best_prefix_len = prefix_len;
462+
}
463+
}
464+
return matched_path;
465+
}
466+
433467
/****************************************************************************
434468
* NEW PATHKEY FORMATION
435469
****************************************************************************/
@@ -1483,13 +1517,17 @@ pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys)
14831517
if (pathkeys == NIL)
14841518
return 0; /* unordered path */
14851519

1520+
#if 0
14861521
if (pathkeys_contained_in(root->query_pathkeys, pathkeys))
14871522
{
14881523
/* It's useful ... or at least the first N keys are */
14891524
return list_length(root->query_pathkeys);
14901525
}
14911526

14921527
return 0; /* path ordering not useful */
1528+
#else
1529+
return pathkeys_get_prefix(root->query_pathkeys, pathkeys);
1530+
#endif
14931531
}
14941532

14951533
/*

src/backend/optimizer/plan/createplan.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4049,17 +4049,6 @@ make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
40494049
0.0,
40504050
work_mem,
40514051
limit_tuples);
4052-
if (lefttree->type == T_IndexOnlyScan && root->simple_rel_array_size == 2)
4053-
{
4054-
RelOptInfo* relinfo = root->simple_rel_array[1];
4055-
IndexOptInfo* indexinfo = linitial(root->simple_rel_array[1]->indexlist);
4056-
IndexOnlyScan* indexscan = (IndexOnlyScan*)lefttree;
4057-
List *index_pathkeys = build_index_pathkeys(root, indexinfo, indexscan->indexorderdir);
4058-
int prefix_len = pathkeys_get_prefix(root->query_pathkeys, index_pathkeys);
4059-
sort_path.total_cost -= sort_path.startup_cost;
4060-
sort_path.startup_cost /= (prefix_len+1);
4061-
sort_path.total_cost += sort_path.startup_cost;
4062-
}
40634052
plan->startup_cost = sort_path.startup_cost;
40644053
plan->total_cost = sort_path.total_cost;
40654054
plan->targetlist = lefttree->targetlist;

src/backend/optimizer/plan/planner.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,10 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
13341334
double dNumGroups = 0;
13351335
bool use_hashed_distinct = false;
13361336
bool tested_hashed_distinct = false;
1337+
Path *cheapest_path;
1338+
Path *sorted_path = NULL;
1339+
Path *partial_sorted_path = NULL;
1340+
Path *best_path = NULL;
13371341

13381342
/* Tweak caller-supplied tuple_fraction if have LIMIT/OFFSET */
13391343
if (parse->limitCount || parse->limitOffset)
@@ -1434,9 +1438,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
14341438
List *rollup_groupclauses = NIL;
14351439
standard_qp_extra qp_extra;
14361440
RelOptInfo *final_rel;
1437-
Path *cheapest_path;
1438-
Path *sorted_path;
1439-
Path *best_path;
14401441

14411442
MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
14421443

@@ -1764,7 +1765,14 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
17641765
root->query_pathkeys,
17651766
NULL,
17661767
tuple_fraction);
1767-
1768+
if (sorted_path == NULL)
1769+
{
1770+
partial_sorted_path =
1771+
get_cheapest_partial_path_for_pathkeys(final_rel->pathlist,
1772+
root->query_pathkeys,
1773+
NULL,
1774+
tuple_fraction);
1775+
}
17681776
/* Don't consider same path in both guises; just wastes effort */
17691777
if (sorted_path == cheapest_path)
17701778
sorted_path = NULL;
@@ -1803,7 +1811,32 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
18031811
/* Presorted path is a loser */
18041812
sorted_path = NULL;
18051813
}
1814+
} else if (partial_sorted_path != NULL) {
1815+
Path sort_path;
1816+
Path partial_sort_path;
1817+
1818+
cost_sort(&sort_path, root, root->query_pathkeys,
1819+
cheapest_path->total_cost,
1820+
path_rows, path_width,
1821+
0.0, work_mem, root->limit_tuples);
1822+
1823+
cost_sort(&partial_sort_path, root, root->query_pathkeys,
1824+
partial_sorted_path->total_cost,
1825+
path_rows, path_width,
1826+
0.0, work_mem, root->limit_tuples);
1827+
1828+
partial_sort_path.total_cost -= partial_sort_path.startup_cost;
1829+
partial_sort_path.startup_cost /= partial_sorted_path->pathkeys->length+1;
1830+
partial_sort_path.total_cost += partial_sort_path.startup_cost;
1831+
1832+
1833+
if (compare_fractional_path_costs(&sort_path, &partial_sort_path,
1834+
tuple_fraction) > 0)
1835+
{
1836+
cheapest_path = partial_sorted_path;
1837+
}
18061838
}
1839+
18071840

18081841
/*
18091842
* Consider whether we want to use hashing instead of sorting.
@@ -2370,6 +2403,12 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
23702403
result_plan,
23712404
root->sort_pathkeys,
23722405
limit_tuples);
2406+
if (partial_sorted_path && best_path == partial_sorted_path)
2407+
{
2408+
result_plan->total_cost -= result_plan->startup_cost;
2409+
result_plan->startup_cost /= partial_sorted_path->pathkeys->length+1;
2410+
result_plan->total_cost += result_plan->startup_cost;
2411+
}
23732412
current_pathkeys = root->sort_pathkeys;
23742413
}
23752414
}

src/include/optimizer/paths.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
175175
List *pathkeys,
176176
Relids required_outer,
177177
double fraction);
178+
extern Path *get_cheapest_partial_path_for_pathkeys(List *paths,
179+
List *pathkeys,
180+
Relids required_outer,
181+
double fraction);
178182
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
179183
ScanDirection scandir);
180184
extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,

0 commit comments

Comments
 (0)