diff options
author | Robert Haas | 2024-08-30 19:11:23 +0000 |
---|---|---|
committer | Robert Haas | 2024-08-30 19:11:23 +0000 |
commit | 9ad86322ddd8713695e3fa74a0287c26a424df30 (patch) | |
tree | 75678b324b0dd706a36079e34bc9c4a2c8237253 | |
parent | 868dc508088e734021099e5716f9e6da4de8337f (diff) |
Split up nested loops.
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 12 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 42 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 1 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 6 | ||||
-rw-r--r-- | src/include/optimizer/cost.h | 4 | ||||
-rw-r--r-- | src/include/optimizer/pathnode.h | 3 | ||||
-rw-r--r-- | src/include/optimizer/paths.h | 29 |
8 files changed, 46 insertions, 59 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 8f18a6f00a..7ed03b33a7 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -894,7 +894,7 @@ set_tablesample_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry * bms_membership(root->all_query_rels) != BMS_SINGLETON) && !(GetTsmRoutine(rte->tablesample->tsmhandler)->repeatable_across_scans)) { - path = (Path *) create_material_path(rel, path); + path = (Path *) create_material_path(rel, path, enable_material); } add_path(rel, path); @@ -3373,12 +3373,16 @@ make_rel_from_joinlist(PlannerInfo *root, List *joinlist) jsa_mask = JSA_FOREIGN; if (enable_hashjoin) jsa_mask |= JSA_HASHJOIN; - if (enable_material) - jsa_mask |= JSA_NESTLOOP_MATERIALIZE; if (enable_mergejoin) jsa_mask |= JSA_MERGEJOIN; if (enable_nestloop) - jsa_mask |= JSA_NESTLOOP; + { + jsa_mask |= JSA_NESTLOOP_PLAIN; + if (enable_material) + jsa_mask |= JSA_NESTLOOP_MATERIALIZE; + if (enable_memoize) + jsa_mask |= JSA_NESTLOOP_MEMOIZE; + } if (enable_partitionwise_join) jsa_mask |= JSA_PARTITIONWISE; diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 19717a5324..38ad8fb50e 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -2481,7 +2481,7 @@ cost_merge_append(Path *path, PlannerInfo *root, */ void cost_material(Path *path, - int input_disabled_nodes, + bool enabled, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width) { @@ -2519,7 +2519,7 @@ cost_material(Path *path, run_cost += seq_page_cost * npages; } - path->disabled_nodes = input_disabled_nodes + (enable_material ? 0 : 1); + path->disabled_nodes = input_disabled_nodes + (enabled ? 0 : 1); path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -3266,7 +3266,7 @@ cost_group(Path *path, PlannerInfo *root, */ void initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, - JoinType jointype, + JoinType jointype, unsigned nestloop_subtype, Path *outer_path, Path *inner_path, JoinPathExtraData *extra) { @@ -3280,7 +3280,7 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, Cost inner_rescan_run_cost; /* Count up disabled nodes. */ - disabled_nodes = (extra->jsa_mask & JSA_NESTLOOP) == 0 ? 1 : 0; + disabled_nodes = (extra->jsa_mask & nestloop_subtype) == 0 ? 1 : 0; disabled_nodes += inner_path->disabled_nodes; disabled_nodes += outer_path->disabled_nodes; diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 4fa6c3d918..d853e2a64e 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -862,6 +862,7 @@ try_nestloop_path(PlannerInfo *root, Path *inner_path, List *pathkeys, JoinType jointype, + unsigned nestloop_subtype, JoinPathExtraData *extra) { Relids required_outer; @@ -946,7 +947,7 @@ try_nestloop_path(PlannerInfo *root, * The latter two steps are expensive enough to make this two-phase * methodology worthwhile. */ - initial_cost_nestloop(root, &workspace, jointype, + initial_cost_nestloop(root, &workspace, jointype, nestloop_subtype, outer_path, inner_path, extra); if (add_path_precheck(joinrel, workspace.disabled_nodes, @@ -984,6 +985,7 @@ try_partial_nestloop_path(PlannerInfo *root, Path *inner_path, List *pathkeys, JoinType jointype, + unsigned nestloop_subtype, JoinPathExtraData *extra) { JoinCostWorkspace workspace; @@ -1031,7 +1033,7 @@ try_partial_nestloop_path(PlannerInfo *root, * Before creating a path, get a quick lower bound on what it is likely to * cost. Bail out right away if it looks terrible. */ - initial_cost_nestloop(root, &workspace, jointype, + initial_cost_nestloop(root, &workspace, jointype, nestloop_subtype, outer_path, inner_path, extra); if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes, workspace.total_cost, pathkeys)) @@ -1939,17 +1941,8 @@ match_unsorted_outer(PlannerInfo *root, if ((extra->jsa_mask & JSA_NESTLOOP_MATERIALIZE) != 0 && inner_cheapest_total != NULL && !ExecMaterializesOutput(inner_cheapest_total->pathtype)) - { matpath = (Path *) - create_material_path(innerrel, inner_cheapest_total); - - /* - * Ignore create_material_path()'s idea of whether the path is - * disabled in general; JSA_NESTLOOP_MATERIALIZE means it is - * acceptable here. - */ - matpath->disabled_nodes = inner_cheapest_total->disabled_nodes; - } + create_material_path(innerrel, inner_cheapest_total, true); } foreach(lc1, outerrel->pathlist) @@ -1997,6 +1990,7 @@ match_unsorted_outer(PlannerInfo *root, inner_cheapest_total, merge_pathkeys, jointype, + JSA_NESTLOOP_PLAIN, extra); } else if (nestjoinOK) @@ -2020,6 +2014,7 @@ match_unsorted_outer(PlannerInfo *root, innerpath, merge_pathkeys, jointype, + JSA_NESTLOOP_PLAIN, extra); /* @@ -2036,6 +2031,7 @@ match_unsorted_outer(PlannerInfo *root, mpath, merge_pathkeys, jointype, + JSA_NESTLOOP_MEMOIZE, extra); } @@ -2047,6 +2043,7 @@ match_unsorted_outer(PlannerInfo *root, matpath, merge_pathkeys, jointype, + JSA_NESTLOOP_MATERIALIZE, extra); } @@ -2188,18 +2185,8 @@ consider_parallel_nestloop(PlannerInfo *root, inner_cheapest_total->parallel_safe && !PATH_PARAM_BY_REL(inner_cheapest_total, outerrel) && !ExecMaterializesOutput(inner_cheapest_total->pathtype)) - { matpath = (Path *) - create_material_path(innerrel, inner_cheapest_total); - Assert(matpath->parallel_safe); - - /* - * Ignore create_material_path()'s idea of whether the path is - * disabled in general; JSA_NESTLOOP_MATERIALIZE means it is - * acceptable here. - */ - matpath->disabled_nodes = inner_cheapest_total->disabled_nodes; - } + create_material_path(innerrel, inner_cheapest_total, true); foreach(lc1, outerrel->partial_pathlist) { @@ -2244,7 +2231,8 @@ consider_parallel_nestloop(PlannerInfo *root, } try_partial_nestloop_path(root, joinrel, outerpath, innerpath, - pathkeys, jointype, extra); + pathkeys, jointype, JSA_NESTLOOP_PLAIN, + extra); /* * Try generating a memoize path and see if that makes the nested @@ -2255,13 +2243,15 @@ consider_parallel_nestloop(PlannerInfo *root, extra); if (mpath != NULL) try_partial_nestloop_path(root, joinrel, outerpath, mpath, - pathkeys, jointype, extra); + pathkeys, jointype, + JSA_NESTLOOP_MEMOIZE, extra); } /* Also consider materialized form of the cheapest inner path */ if (matpath != NULL) try_partial_nestloop_path(root, joinrel, outerpath, matpath, - pathkeys, jointype, extra); + pathkeys, jointype, + JSA_NESTLOOP_MATERIALIZE, extra); } } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 8e0e5977a9..7372232b81 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -6550,6 +6550,7 @@ materialize_finished_plan(Plan *subplan) /* Set cost data */ cost_material(&matpath, + enable_material, subplan->disabled_nodes, subplan->startup_cost, subplan->total_cost, diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index fc97bf6ee2..a704d0cd7b 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1631,7 +1631,7 @@ create_group_result_path(PlannerInfo *root, RelOptInfo *rel, * pathnode. */ MaterialPath * -create_material_path(RelOptInfo *rel, Path *subpath) +create_material_path(RelOptInfo *rel, Path *subpath, bool enabled) { MaterialPath *pathnode = makeNode(MaterialPath); @@ -1650,6 +1650,7 @@ create_material_path(RelOptInfo *rel, Path *subpath) pathnode->subpath = subpath; cost_material(&pathnode->path, + enabled, subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, @@ -4158,7 +4159,8 @@ reparameterize_path(PlannerInfo *root, Path *path, loop_count); if (spath == NULL) return NULL; - return (Path *) create_material_path(rel, spath); + return (Path *) create_material_path(rel, spath, + enable_material); } case T_Memoize: { diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 854a782944..071a8749cf 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -125,7 +125,7 @@ extern void cost_merge_append(Path *path, PlannerInfo *root, Cost input_startup_cost, Cost input_total_cost, double tuples); extern void cost_material(Path *path, - int input_disabled_nodes, + bool enabled, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width); extern void cost_agg(Path *path, PlannerInfo *root, @@ -148,7 +148,7 @@ extern void cost_group(Path *path, PlannerInfo *root, double input_tuples); extern void initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, - JoinType jointype, + JoinType jointype, unsigned nestloop_subtype, Path *outer_path, Path *inner_path, JoinPathExtraData *extra); extern void final_cost_nestloop(PlannerInfo *root, NestPath *path, diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 266c551cac..ed2e3a1c8b 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -82,7 +82,8 @@ extern GroupResultPath *create_group_result_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *havingqual); -extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath); +extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath, + bool enabled); extern MemoizePath *create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 4177d7a45a..94779eff9a 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -25,30 +25,19 @@ * mask is computed on the basis of the various enable_* GUCs, and can be * overriden by hooks. * - * JSA_FOREIGN means that it's OK for a FDW to produce join paths. - * - * JSA_MERGEJOIN means that a mergejoin is OK. - * - * JSA_NESTLOOP means that a nested loop is OK in general. - * - * JSA_NESTLOOP_MATERIALIZE and JSA_NESTLOOP_NO_MATERIALIZE mean that it's - * OK for a nested loop to materialize or not materialize the inner side. - * JSA_NESTLOOP_MEMOIZE and JSA_NESTLOOP_NO_MEMOIZE mean that it's OK for - * a nested loop to memoize or not memoize the inner side. - * - * JSA_HASHJOIN means that a hash join is OK. - * - * JSA_PARTITIONWISE means that a partitionwise join is OK. + * We have five main join strategie: a foreign join (when supported by the + * relevant FDW), a merge join, a nested loop, a hash join, and a partitionwise + * join. Nested loops are further subdivided depending on whether the inner + * side of the join is materialized, memoized, or neither (which we here call + * a "plain" nested loop). */ #define JSA_FOREIGN 0x0001 #define JSA_MERGEJOIN 0x0002 -#define JSA_NESTLOOP 0x0004 +#define JSA_NESTLOOP_PLAIN 0x0004 #define JSA_NESTLOOP_MATERIALIZE 0x0008 -#define JSA_NESTLOOP_NO_MATERIALIZE 0x0010 -#define JSA_NESTLOOP_MEMOIZE 0x0020 -#define JSA_NESTLOOP_NO_MEMOIZE 0x0040 -#define JSA_HASHJOIN 0x0080 -#define JSA_PARTITIONWISE 0x0100 +#define JSA_NESTLOOP_MEMOIZE 0x0010 +#define JSA_HASHJOIN 0x0020 +#define JSA_PARTITIONWISE 0x0040 /* * allpaths.c |