Skip to content

Commit a71f101

Browse files
committed
Preparatory refactoring for parallel merge join support.
Extract the logic used by hash_inner_and_outer into a separate function, get_cheapest_parallel_safe_total_inner, so that it can also be used to plan parallel merge joins. Also, add a require_parallel_safe argument to the existing function get_cheapest_path_for_pathkeys, because parallel merge join needs to find the cheapest path for a given set of pathkeys that is parallel-safe, not just the cheapest one overall. Patch by me, reviewed by Dilip Kumar. Discussion: http://postgr.es/m/CA+TgmoYOv+dFK0MWW6366dFj_xTnohQfoBDrHyB7d1oZhrgPjA@mail.gmail.com
1 parent 655393a commit a71f101

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

src/backend/optimizer/path/allpaths.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -1447,12 +1447,14 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
14471447
get_cheapest_path_for_pathkeys(childrel->pathlist,
14481448
pathkeys,
14491449
NULL,
1450-
STARTUP_COST);
1450+
STARTUP_COST,
1451+
false);
14511452
cheapest_total =
14521453
get_cheapest_path_for_pathkeys(childrel->pathlist,
14531454
pathkeys,
14541455
NULL,
1455-
TOTAL_COST);
1456+
TOTAL_COST,
1457+
false);
14561458

14571459
/*
14581460
* If we can't find any paths with the right order just use the
@@ -1517,7 +1519,8 @@ get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo *rel,
15171519
cheapest = get_cheapest_path_for_pathkeys(rel->pathlist,
15181520
NIL,
15191521
required_outer,
1520-
TOTAL_COST);
1522+
TOTAL_COST,
1523+
false);
15211524
Assert(cheapest != NULL);
15221525
if (bms_equal(PATH_REQ_OUTER(cheapest), required_outer))
15231526
return cheapest;

src/backend/optimizer/path/joinpath.c

+6-17
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,8 @@ generate_mergejoin_paths(PlannerInfo *root,
936936
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
937937
trialsortkeys,
938938
NULL,
939-
TOTAL_COST);
939+
TOTAL_COST,
940+
false);
940941
if (innerpath != NULL &&
941942
(cheapest_total_inner == NULL ||
942943
compare_path_costs(innerpath, cheapest_total_inner,
@@ -971,7 +972,8 @@ generate_mergejoin_paths(PlannerInfo *root,
971972
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
972973
trialsortkeys,
973974
NULL,
974-
STARTUP_COST);
975+
STARTUP_COST,
976+
false);
975977
if (innerpath != NULL &&
976978
(cheapest_startup_inner == NULL ||
977979
compare_path_costs(innerpath, cheapest_startup_inner,
@@ -1517,21 +1519,8 @@ hash_inner_and_outer(PlannerInfo *root,
15171519
if (cheapest_total_inner->parallel_safe)
15181520
cheapest_safe_inner = cheapest_total_inner;
15191521
else if (save_jointype != JOIN_UNIQUE_INNER)
1520-
{
1521-
ListCell *lc;
1522-
1523-
foreach(lc, innerrel->pathlist)
1524-
{
1525-
Path *innerpath = (Path *) lfirst(lc);
1526-
1527-
if (innerpath->parallel_safe &&
1528-
bms_is_empty(PATH_REQ_OUTER(innerpath)))
1529-
{
1530-
cheapest_safe_inner = innerpath;
1531-
break;
1532-
}
1533-
}
1534-
}
1522+
cheapest_safe_inner =
1523+
get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
15351524

15361525
if (cheapest_safe_inner != NULL)
15371526
try_partial_hashjoin_path(root, joinrel,

src/backend/optimizer/path/pathkeys.c

+28-1
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,13 @@ pathkeys_contained_in(List *keys1, List *keys2)
337337
* 'pathkeys' represents a required ordering (in canonical form!)
338338
* 'required_outer' denotes allowable outer relations for parameterized paths
339339
* 'cost_criterion' is STARTUP_COST or TOTAL_COST
340+
* 'require_parallel_safe' causes us to consider only parallel-safe paths
340341
*/
341342
Path *
342343
get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
343344
Relids required_outer,
344-
CostSelector cost_criterion)
345+
CostSelector cost_criterion,
346+
bool require_parallel_safe)
345347
{
346348
Path *matched_path = NULL;
347349
ListCell *l;
@@ -358,6 +360,9 @@ get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
358360
compare_path_costs(matched_path, path, cost_criterion) <= 0)
359361
continue;
360362

363+
if (require_parallel_safe && !path->parallel_safe)
364+
continue;
365+
361366
if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
362367
bms_is_subset(PATH_REQ_OUTER(path), required_outer))
363368
matched_path = path;
@@ -407,6 +412,28 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
407412
return matched_path;
408413
}
409414

415+
416+
/*
417+
* get_cheapest_parallel_safe_total_inner
418+
* Find the unparameterized parallel-safe path with the least total cost.
419+
*/
420+
Path *
421+
get_cheapest_parallel_safe_total_inner(List *paths)
422+
{
423+
ListCell *l;
424+
425+
foreach(l, paths)
426+
{
427+
Path *innerpath = (Path *) lfirst(l);
428+
429+
if (innerpath->parallel_safe &&
430+
bms_is_empty(PATH_REQ_OUTER(innerpath)))
431+
return innerpath;
432+
}
433+
434+
return NULL;
435+
}
436+
410437
/****************************************************************************
411438
* NEW PATHKEY FORMATION
412439
****************************************************************************/

src/include/optimizer/paths.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,13 @@ extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
182182
extern bool pathkeys_contained_in(List *keys1, List *keys2);
183183
extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
184184
Relids required_outer,
185-
CostSelector cost_criterion);
185+
CostSelector cost_criterion,
186+
bool require_parallel_safe);
186187
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
187188
List *pathkeys,
188189
Relids required_outer,
189190
double fraction);
191+
extern Path *get_cheapest_parallel_safe_total_inner(List *paths);
190192
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
191193
ScanDirection scandir);
192194
extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,

0 commit comments

Comments
 (0)