Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc3c5c02

Browse files
committed
Simplify LATERAL-related calculations within add_paths_to_joinrel().
While convincing myself that commit7e19db0 would solve both ofthe problems recently reported by Andreas Seltenreich, I realized thatadd_paths_to_joinrel's handling of LATERAL restrictions could be madenoticeably simpler and faster if we were to retain the minimum possibleparameterization for each joinrel (that is, the set of relids supplyingunsatisfied lateral references in it). We already retain that forbaserels, in RelOptInfo.lateral_relids, so we can use that field forjoinrels too.This is a back-port of commitedca44b.I originally intended not to back-patch that, but additional hackingin this area turns out to be needed, making it necessary not optionalto compute lateral_relids for joinrels. In preparation for those fixes,sync the relevant code with HEAD as much as practical. (I did not riskrearranging fields of RelOptInfo in released branches, however.)
1 parent4acee11 commitc3c5c02

File tree

4 files changed

+24
-67
lines changed

4 files changed

+24
-67
lines changed

‎src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1858,13 +1858,13 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
18581858
WRITE_NODE_FIELD(cheapest_total_path);
18591859
WRITE_NODE_FIELD(cheapest_unique_path);
18601860
WRITE_NODE_FIELD(cheapest_parameterized_paths);
1861+
WRITE_BITMAPSET_FIELD(lateral_relids);
18611862
WRITE_UINT_FIELD(relid);
18621863
WRITE_OID_FIELD(reltablespace);
18631864
WRITE_ENUM_FIELD(rtekind,RTEKind);
18641865
WRITE_INT_FIELD(min_attr);
18651866
WRITE_INT_FIELD(max_attr);
18661867
WRITE_NODE_FIELD(lateral_vars);
1867-
WRITE_BITMAPSET_FIELD(lateral_relids);
18681868
WRITE_BITMAPSET_FIELD(lateral_referencers);
18691869
WRITE_NODE_FIELD(indexlist);
18701870
WRITE_UINT_FIELD(pages);

‎src/backend/optimizer/path/joinpath.c

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ add_paths_to_joinrel(PlannerInfo *root,
8686
extra.mergeclause_list=NIL;
8787
extra.sjinfo=sjinfo;
8888
extra.param_source_rels=NULL;
89-
extra.extra_lateral_rels=NULL;
9089

9190
/*
9291
* Find potential mergejoin clauses. We can skip this if we are not
@@ -151,60 +150,14 @@ add_paths_to_joinrel(PlannerInfo *root,
151150
}
152151

153152
/*
154-
* However, when a LATERAL subquery is involved, we have to be a bit
155-
* laxer, because there will simply not be any paths for the joinrel that
156-
* aren't parameterized by whatever the subquery is parameterized by,
157-
* unless its parameterization is resolved within the joinrel. Hence, add
158-
* to param_source_rels anything that is laterally referenced in either
159-
* input and is not in the join already.
153+
* However, when a LATERAL subquery is involved, there will simply not be
154+
* any paths for the joinrel that aren't parameterized by whatever the
155+
* subquery is parameterized by, unless its parameterization is resolved
156+
* within the joinrel. So we might as well allow additional dependencies
157+
* on whatever residual lateral dependencies the joinrel will have.
160158
*/
161-
foreach(lc,root->lateral_info_list)
162-
{
163-
LateralJoinInfo*ljinfo= (LateralJoinInfo*)lfirst(lc);
164-
165-
if (bms_is_subset(ljinfo->lateral_rhs,joinrel->relids))
166-
extra.param_source_rels=bms_join(extra.param_source_rels,
167-
bms_difference(ljinfo->lateral_lhs,
168-
joinrel->relids));
169-
}
170-
171-
/*
172-
* Another issue created by LATERAL references is that PlaceHolderVars
173-
* that need to be computed at this join level might contain lateral
174-
* references to rels not in the join, meaning that the paths for the join
175-
* would need to be marked as parameterized by those rels, independently
176-
* of all other considerations. Set extra_lateral_rels to the set of such
177-
* rels. This will not affect our decisions as to which paths to
178-
* generate; we merely add these rels to their required_outer sets.
179-
*/
180-
foreach(lc,root->placeholder_list)
181-
{
182-
PlaceHolderInfo*phinfo= (PlaceHolderInfo*)lfirst(lc);
183-
184-
/* PHVs without lateral refs can be skipped over quickly */
185-
if (phinfo->ph_lateral==NULL)
186-
continue;
187-
/* Is it due to be evaluated at this join, and not in either input? */
188-
if (bms_is_subset(phinfo->ph_eval_at,joinrel->relids)&&
189-
!bms_is_subset(phinfo->ph_eval_at,outerrel->relids)&&
190-
!bms_is_subset(phinfo->ph_eval_at,innerrel->relids))
191-
{
192-
/* Yes, remember its lateral rels */
193-
extra.extra_lateral_rels=bms_add_members(extra.extra_lateral_rels,
194-
phinfo->ph_lateral);
195-
}
196-
}
197-
198-
/*
199-
* Make sure extra_lateral_rels doesn't list anything within the join, and
200-
* that it's NULL if empty. (This allows us to use bms_add_members to add
201-
* it to required_outer below, while preserving the property that
202-
* required_outer is exactly NULL if empty.)
203-
*/
204-
extra.extra_lateral_rels=bms_del_members(extra.extra_lateral_rels,
205-
joinrel->relids);
206-
if (bms_is_empty(extra.extra_lateral_rels))
207-
extra.extra_lateral_rels=NULL;
159+
extra.param_source_rels=bms_add_members(extra.param_source_rels,
160+
joinrel->lateral_relids);
208161

209162
/*
210163
* 1. Consider mergejoin paths where both relations must be explicitly
@@ -386,9 +339,13 @@ try_nestloop_path(PlannerInfo *root,
386339

387340
/*
388341
* Independently of that, add parameterization needed for any
389-
* PlaceHolderVars that need to be computed at the join.
342+
* PlaceHolderVars that need to be computed at the join. We can handle
343+
* that just by adding joinrel->lateral_relids; that might include some
344+
* rels that are already in required_outer, but no harm done. (Note that
345+
* lateral_relids is exactly NULL if empty, so this will not break the
346+
* property that required_outer is too.)
390347
*/
391-
required_outer=bms_add_members(required_outer,extra->extra_lateral_rels);
348+
required_outer=bms_add_members(required_outer,joinrel->lateral_relids);
392349

393350
/*
394351
* Do a precheck to quickly eliminate obviously-inferior paths. We
@@ -465,7 +422,7 @@ try_mergejoin_path(PlannerInfo *root,
465422
* Independently of that, add parameterization needed for any
466423
* PlaceHolderVars that need to be computed at the join.
467424
*/
468-
required_outer=bms_add_members(required_outer,extra->extra_lateral_rels);
425+
required_outer=bms_add_members(required_outer,joinrel->lateral_relids);
469426

470427
/*
471428
* If the given paths are already well enough ordered, we can skip doing
@@ -547,7 +504,7 @@ try_hashjoin_path(PlannerInfo *root,
547504
* Independently of that, add parameterization needed for any
548505
* PlaceHolderVars that need to be computed at the join.
549506
*/
550-
required_outer=bms_add_members(required_outer,extra->extra_lateral_rels);
507+
required_outer=bms_add_members(required_outer,joinrel->lateral_relids);
551508

552509
/*
553510
* See comments in try_nestloop_path(). Also note that hashjoin paths

‎src/backend/optimizer/util/relnode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
109109
rel->cheapest_total_path=NULL;
110110
rel->cheapest_unique_path=NULL;
111111
rel->cheapest_parameterized_paths=NIL;
112+
rel->lateral_relids=NULL;
112113
rel->relid=relid;
113114
rel->rtekind=rte->rtekind;
114115
/* min_attr, max_attr, attr_needed, attr_widths are set below */
115116
rel->lateral_vars=NIL;
116-
rel->lateral_relids=NULL;
117117
rel->lateral_referencers=NULL;
118118
rel->indexlist=NIL;
119119
rel->pages=0;
@@ -370,14 +370,14 @@ build_join_rel(PlannerInfo *root,
370370
joinrel->cheapest_total_path=NULL;
371371
joinrel->cheapest_unique_path=NULL;
372372
joinrel->cheapest_parameterized_paths=NIL;
373+
joinrel->lateral_relids=min_join_parameterization(root,joinrel->relids);
373374
joinrel->relid=0;/* indicates not a baserel */
374375
joinrel->rtekind=RTE_JOIN;
375376
joinrel->min_attr=0;
376377
joinrel->max_attr=0;
377378
joinrel->attr_needed=NULL;
378379
joinrel->attr_widths=NULL;
379380
joinrel->lateral_vars=NIL;
380-
joinrel->lateral_relids=NULL;
381381
joinrel->lateral_referencers=NULL;
382382
joinrel->indexlist=NIL;
383383
joinrel->pages=0;

‎src/include/nodes/relation.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ typedef struct PlannerInfo
344344
*(no duplicates) output from relation; NULL if not yet requested
345345
*cheapest_parameterized_paths - best paths for their parameterizations;
346346
*always includes cheapest_total_path, even if that's unparameterized
347+
*lateral_relids - required outer rels for LATERAL, as a Relids set
347348
*
348349
* If the relation is a base relation it will have these fields set:
349350
*
@@ -358,8 +359,6 @@ typedef struct PlannerInfo
358359
* zero means not computed yet
359360
*lateral_vars - lateral cross-references of rel, if any (list of
360361
* Vars and PlaceHolderVars)
361-
*lateral_relids - required outer rels for LATERAL, as a Relids set
362-
* (for child rels this can be more than lateral_vars)
363362
*lateral_referencers - relids of rels that reference this one laterally
364363
*indexlist - list of IndexOptInfo nodes for relation's indexes
365364
*(always NIL if it's not a table)
@@ -375,7 +374,7 @@ typedef struct PlannerInfo
375374
*set_subquery_pathlist processes the object.
376375
*
377376
*For otherrels that are appendrel members, these fields are filled
378-
*in just as for a baserel.
377+
*in just as for a baserel, except we don't bother with lateral_vars.
379378
*
380379
* If the relation is either a foreign table or a join of foreign tables that
381380
* all belong to the same foreign server, these fields will be set:
@@ -449,6 +448,10 @@ typedef struct RelOptInfo
449448
structPath*cheapest_unique_path;
450449
List*cheapest_parameterized_paths;
451450

451+
/* parameterization information needed for both base rels and join rels */
452+
/* (see also lateral_vars and lateral_referencers) */
453+
Relidslateral_relids;/* minimum parameterization of rel */
454+
452455
/* information about a base rel (not set for join rels!) */
453456
Indexrelid;
454457
Oidreltablespace;/* containing tablespace */
@@ -458,7 +461,6 @@ typedef struct RelOptInfo
458461
Relids*attr_needed;/* array indexed [min_attr .. max_attr] */
459462
int32*attr_widths;/* array indexed [min_attr .. max_attr] */
460463
List*lateral_vars;/* LATERAL Vars and PHVs referenced by rel */
461-
Relidslateral_relids;/* minimum parameterization of rel */
462464
Relidslateral_referencers;/* rels that reference me laterally */
463465
List*indexlist;/* list of IndexOptInfo */
464466
BlockNumberpages;/* size estimates derived from pg_class */
@@ -1690,7 +1692,6 @@ typedef struct SemiAntiJoinFactors
16901692
* sjinfo is extra info about special joins for selectivity estimation
16911693
* semifactors is as shown above (only valid for SEMI or ANTI joins)
16921694
* param_source_rels are OK targets for parameterization of result paths
1693-
* extra_lateral_rels are additional parameterization for result paths
16941695
*/
16951696
typedefstructJoinPathExtraData
16961697
{
@@ -1699,7 +1700,6 @@ typedef struct JoinPathExtraData
16991700
SpecialJoinInfo*sjinfo;
17001701
SemiAntiJoinFactorssemifactors;
17011702
Relidsparam_source_rels;
1702-
Relidsextra_lateral_rels;
17031703
}JoinPathExtraData;
17041704

17051705
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp