mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
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
This commit is contained in:
@ -1447,12 +1447,14 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
|
|||||||
get_cheapest_path_for_pathkeys(childrel->pathlist,
|
get_cheapest_path_for_pathkeys(childrel->pathlist,
|
||||||
pathkeys,
|
pathkeys,
|
||||||
NULL,
|
NULL,
|
||||||
STARTUP_COST);
|
STARTUP_COST,
|
||||||
|
false);
|
||||||
cheapest_total =
|
cheapest_total =
|
||||||
get_cheapest_path_for_pathkeys(childrel->pathlist,
|
get_cheapest_path_for_pathkeys(childrel->pathlist,
|
||||||
pathkeys,
|
pathkeys,
|
||||||
NULL,
|
NULL,
|
||||||
TOTAL_COST);
|
TOTAL_COST,
|
||||||
|
false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we can't find any paths with the right order just use the
|
* 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,
|
|||||||
cheapest = get_cheapest_path_for_pathkeys(rel->pathlist,
|
cheapest = get_cheapest_path_for_pathkeys(rel->pathlist,
|
||||||
NIL,
|
NIL,
|
||||||
required_outer,
|
required_outer,
|
||||||
TOTAL_COST);
|
TOTAL_COST,
|
||||||
|
false);
|
||||||
Assert(cheapest != NULL);
|
Assert(cheapest != NULL);
|
||||||
if (bms_equal(PATH_REQ_OUTER(cheapest), required_outer))
|
if (bms_equal(PATH_REQ_OUTER(cheapest), required_outer))
|
||||||
return cheapest;
|
return cheapest;
|
||||||
|
@ -936,7 +936,8 @@ generate_mergejoin_paths(PlannerInfo *root,
|
|||||||
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
|
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
|
||||||
trialsortkeys,
|
trialsortkeys,
|
||||||
NULL,
|
NULL,
|
||||||
TOTAL_COST);
|
TOTAL_COST,
|
||||||
|
false);
|
||||||
if (innerpath != NULL &&
|
if (innerpath != NULL &&
|
||||||
(cheapest_total_inner == NULL ||
|
(cheapest_total_inner == NULL ||
|
||||||
compare_path_costs(innerpath, cheapest_total_inner,
|
compare_path_costs(innerpath, cheapest_total_inner,
|
||||||
@ -971,7 +972,8 @@ generate_mergejoin_paths(PlannerInfo *root,
|
|||||||
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
|
innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
|
||||||
trialsortkeys,
|
trialsortkeys,
|
||||||
NULL,
|
NULL,
|
||||||
STARTUP_COST);
|
STARTUP_COST,
|
||||||
|
false);
|
||||||
if (innerpath != NULL &&
|
if (innerpath != NULL &&
|
||||||
(cheapest_startup_inner == NULL ||
|
(cheapest_startup_inner == NULL ||
|
||||||
compare_path_costs(innerpath, cheapest_startup_inner,
|
compare_path_costs(innerpath, cheapest_startup_inner,
|
||||||
@ -1517,21 +1519,8 @@ hash_inner_and_outer(PlannerInfo *root,
|
|||||||
if (cheapest_total_inner->parallel_safe)
|
if (cheapest_total_inner->parallel_safe)
|
||||||
cheapest_safe_inner = cheapest_total_inner;
|
cheapest_safe_inner = cheapest_total_inner;
|
||||||
else if (save_jointype != JOIN_UNIQUE_INNER)
|
else if (save_jointype != JOIN_UNIQUE_INNER)
|
||||||
{
|
cheapest_safe_inner =
|
||||||
ListCell *lc;
|
get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
|
||||||
|
|
||||||
foreach(lc, innerrel->pathlist)
|
|
||||||
{
|
|
||||||
Path *innerpath = (Path *) lfirst(lc);
|
|
||||||
|
|
||||||
if (innerpath->parallel_safe &&
|
|
||||||
bms_is_empty(PATH_REQ_OUTER(innerpath)))
|
|
||||||
{
|
|
||||||
cheapest_safe_inner = innerpath;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cheapest_safe_inner != NULL)
|
if (cheapest_safe_inner != NULL)
|
||||||
try_partial_hashjoin_path(root, joinrel,
|
try_partial_hashjoin_path(root, joinrel,
|
||||||
|
@ -337,11 +337,13 @@ pathkeys_contained_in(List *keys1, List *keys2)
|
|||||||
* 'pathkeys' represents a required ordering (in canonical form!)
|
* 'pathkeys' represents a required ordering (in canonical form!)
|
||||||
* 'required_outer' denotes allowable outer relations for parameterized paths
|
* 'required_outer' denotes allowable outer relations for parameterized paths
|
||||||
* 'cost_criterion' is STARTUP_COST or TOTAL_COST
|
* 'cost_criterion' is STARTUP_COST or TOTAL_COST
|
||||||
|
* 'require_parallel_safe' causes us to consider only parallel-safe paths
|
||||||
*/
|
*/
|
||||||
Path *
|
Path *
|
||||||
get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
||||||
Relids required_outer,
|
Relids required_outer,
|
||||||
CostSelector cost_criterion)
|
CostSelector cost_criterion,
|
||||||
|
bool require_parallel_safe)
|
||||||
{
|
{
|
||||||
Path *matched_path = NULL;
|
Path *matched_path = NULL;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
@ -358,6 +360,9 @@ get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
|||||||
compare_path_costs(matched_path, path, cost_criterion) <= 0)
|
compare_path_costs(matched_path, path, cost_criterion) <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (require_parallel_safe && !path->parallel_safe)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
|
if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
|
||||||
bms_is_subset(PATH_REQ_OUTER(path), required_outer))
|
bms_is_subset(PATH_REQ_OUTER(path), required_outer))
|
||||||
matched_path = path;
|
matched_path = path;
|
||||||
@ -407,6 +412,28 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
|
|||||||
return matched_path;
|
return matched_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_cheapest_parallel_safe_total_inner
|
||||||
|
* Find the unparameterized parallel-safe path with the least total cost.
|
||||||
|
*/
|
||||||
|
Path *
|
||||||
|
get_cheapest_parallel_safe_total_inner(List *paths)
|
||||||
|
{
|
||||||
|
ListCell *l;
|
||||||
|
|
||||||
|
foreach(l, paths)
|
||||||
|
{
|
||||||
|
Path *innerpath = (Path *) lfirst(l);
|
||||||
|
|
||||||
|
if (innerpath->parallel_safe &&
|
||||||
|
bms_is_empty(PATH_REQ_OUTER(innerpath)))
|
||||||
|
return innerpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NEW PATHKEY FORMATION
|
* NEW PATHKEY FORMATION
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -182,11 +182,13 @@ extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
|
|||||||
extern bool pathkeys_contained_in(List *keys1, List *keys2);
|
extern bool pathkeys_contained_in(List *keys1, List *keys2);
|
||||||
extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
||||||
Relids required_outer,
|
Relids required_outer,
|
||||||
CostSelector cost_criterion);
|
CostSelector cost_criterion,
|
||||||
|
bool require_parallel_safe);
|
||||||
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
||||||
List *pathkeys,
|
List *pathkeys,
|
||||||
Relids required_outer,
|
Relids required_outer,
|
||||||
double fraction);
|
double fraction);
|
||||||
|
extern Path *get_cheapest_parallel_safe_total_inner(List *paths);
|
||||||
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
|
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
|
||||||
ScanDirection scandir);
|
ScanDirection scandir);
|
||||||
extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,
|
extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,
|
||||||
|
Reference in New Issue
Block a user