Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2f17b57

Browse files
committed
Improve performance of adjust_appendrel_attrs_multilevel.
The present implementations of adjust_appendrel_attrs_multilevel and its sibling adjust_child_relids_multilevel are very messy, because they work by reconstructing the relids of the child's immediate parent and then seeing if that's bms_equal to the relids of the target parent. Aside from being quite inefficient, this will not work with planned future changes to make joinrels' relid sets contain outer-join relids in addition to baserels. The whole thing can be solved at a stroke by adding explicit parent and top_parent links to child RelOptInfos, and making these functions work with RelOptInfo pointers instead of relids. Doing that is simpler for most callers, too. In my original version of this patch, I got rid of RelOptInfo.top_parent_relids on the grounds that it was now redundant. However, that adds a lot of code churn in places that otherwise would not need changing, and arguably the extra indirection needed to fetch top_parent->relids in those places costs something. So this version leaves that field in place. Discussion: https://postgr.es/m/553080.1657481916@sss.pgh.pa.us
1 parent ec97db3 commit 2f17b57

File tree

8 files changed

+83
-94
lines changed

8 files changed

+83
-94
lines changed

src/backend/optimizer/path/equivclass.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,8 +1760,8 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
17601760
if (IS_OTHER_REL(inner_rel) && result != NIL)
17611761
result = (List *) adjust_appendrel_attrs_multilevel(root,
17621762
(Node *) result,
1763-
inner_rel->relids,
1764-
inner_rel->top_parent_relids);
1763+
inner_rel,
1764+
inner_rel->top_parent);
17651765

17661766
return result;
17671767
}
@@ -2626,8 +2626,8 @@ add_child_rel_equivalences(PlannerInfo *root,
26262626
child_expr = (Expr *)
26272627
adjust_appendrel_attrs_multilevel(root,
26282628
(Node *) cur_em->em_expr,
2629-
child_relids,
2630-
top_parent_relids);
2629+
child_rel,
2630+
child_rel->top_parent);
26312631
}
26322632

26332633
/*
@@ -2768,8 +2768,8 @@ add_child_join_rel_equivalences(PlannerInfo *root,
27682768
child_expr = (Expr *)
27692769
adjust_appendrel_attrs_multilevel(root,
27702770
(Node *) cur_em->em_expr,
2771-
child_relids,
2772-
top_parent_relids);
2771+
child_joinrel,
2772+
child_joinrel->top_parent);
27732773
}
27742774

27752775
/*
@@ -2791,8 +2791,8 @@ add_child_join_rel_equivalences(PlannerInfo *root,
27912791
new_nullable_relids =
27922792
adjust_child_relids_multilevel(root,
27932793
new_nullable_relids,
2794-
child_relids,
2795-
top_parent_relids);
2794+
child_joinrel,
2795+
child_joinrel->top_parent);
27962796

27972797
(void) add_eq_member(cur_ec, child_expr,
27982798
new_relids, new_nullable_relids,

src/backend/optimizer/plan/planner.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,8 +1793,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
17931793
withCheckOptions = (List *)
17941794
adjust_appendrel_attrs_multilevel(root,
17951795
(Node *) withCheckOptions,
1796-
this_result_rel->relids,
1797-
top_result_rel->relids);
1796+
this_result_rel,
1797+
top_result_rel);
17981798
withCheckOptionLists = lappend(withCheckOptionLists,
17991799
withCheckOptions);
18001800
}
@@ -1806,8 +1806,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
18061806
returningList = (List *)
18071807
adjust_appendrel_attrs_multilevel(root,
18081808
(Node *) returningList,
1809-
this_result_rel->relids,
1810-
top_result_rel->relids);
1809+
this_result_rel,
1810+
top_result_rel);
18111811
returningLists = lappend(returningLists,
18121812
returningList);
18131813
}
@@ -1828,13 +1828,13 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
18281828
leaf_action->qual =
18291829
adjust_appendrel_attrs_multilevel(root,
18301830
(Node *) action->qual,
1831-
this_result_rel->relids,
1832-
top_result_rel->relids);
1831+
this_result_rel,
1832+
top_result_rel);
18331833
leaf_action->targetList = (List *)
18341834
adjust_appendrel_attrs_multilevel(root,
18351835
(Node *) action->targetList,
1836-
this_result_rel->relids,
1837-
top_result_rel->relids);
1836+
this_result_rel,
1837+
top_result_rel);
18381838
if (leaf_action->commandType == CMD_UPDATE)
18391839
leaf_action->updateColnos =
18401840
adjust_inherited_attnums_multilevel(root,

src/backend/optimizer/util/appendinfo.c

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -479,39 +479,34 @@ adjust_appendrel_attrs_mutator(Node *node,
479479

480480
/*
481481
* adjust_appendrel_attrs_multilevel
482-
* Apply Var translations from a toplevel appendrel parent down to a child.
482+
* Apply Var translations from an appendrel parent down to a child.
483483
*
484-
* In some cases we need to translate expressions referencing a parent relation
485-
* to reference an appendrel child that's multiple levels removed from it.
484+
* Replace Vars in the "node" expression that reference "parentrel" with
485+
* the appropriate Vars for "childrel". childrel can be more than one
486+
* inheritance level removed from parentrel.
486487
*/
487488
Node *
488489
adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
489-
Relids child_relids,
490-
Relids top_parent_relids)
490+
RelOptInfo *childrel,
491+
RelOptInfo *parentrel)
491492
{
492493
AppendRelInfo **appinfos;
493-
Bitmapset *parent_relids = NULL;
494494
int nappinfos;
495-
int cnt;
496-
497-
Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
498-
499-
appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
500495

501-
/* Construct relids set for the immediate parent of given child. */
502-
for (cnt = 0; cnt < nappinfos; cnt++)
496+
/* Recurse if immediate parent is not the top parent. */
497+
if (childrel->parent != parentrel)
503498
{
504-
AppendRelInfo *appinfo = appinfos[cnt];
505-
506-
parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
499+
if (childrel->parent)
500+
node = adjust_appendrel_attrs_multilevel(root, node,
501+
childrel->parent,
502+
parentrel);
503+
else
504+
elog(ERROR, "childrel is not a child of parentrel");
507505
}
508506

509-
/* Recurse if immediate parent is not the top parent. */
510-
if (!bms_equal(parent_relids, top_parent_relids))
511-
node = adjust_appendrel_attrs_multilevel(root, node, parent_relids,
512-
top_parent_relids);
507+
/* Now translate for this child. */
508+
appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
513509

514-
/* Now translate for this child */
515510
node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
516511

517512
pfree(appinfos);
@@ -554,56 +549,43 @@ adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
554549
}
555550

556551
/*
557-
* Replace any relid present in top_parent_relids with its child in
558-
* child_relids. Members of child_relids can be multiple levels below top
559-
* parent in the partition hierarchy.
552+
* Substitute child's relids for parent's relids in a Relid set.
553+
* The childrel can be multiple inheritance levels below the parent.
560554
*/
561555
Relids
562556
adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
563-
Relids child_relids, Relids top_parent_relids)
557+
RelOptInfo *childrel,
558+
RelOptInfo *parentrel)
564559
{
565560
AppendRelInfo **appinfos;
566561
int nappinfos;
567-
Relids parent_relids = NULL;
568-
Relids result;
569-
Relids tmp_result = NULL;
570-
int cnt;
571562

572563
/*
573-
* If the given relids set doesn't contain any of the top parent relids,
574-
* it will remain unchanged.
564+
* If the given relids set doesn't contain any of the parent relids, it
565+
* will remain unchanged.
575566
*/
576-
if (!bms_overlap(relids, top_parent_relids))
567+
if (!bms_overlap(relids, parentrel->relids))
577568
return relids;
578569

579-
appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
580-
581-
/* Construct relids set for the immediate parent of the given child. */
582-
for (cnt = 0; cnt < nappinfos; cnt++)
583-
{
584-
AppendRelInfo *appinfo = appinfos[cnt];
585-
586-
parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
587-
}
588-
589570
/* Recurse if immediate parent is not the top parent. */
590-
if (!bms_equal(parent_relids, top_parent_relids))
571+
if (childrel->parent != parentrel)
591572
{
592-
tmp_result = adjust_child_relids_multilevel(root, relids,
593-
parent_relids,
594-
top_parent_relids);
595-
relids = tmp_result;
573+
if (childrel->parent)
574+
relids = adjust_child_relids_multilevel(root, relids,
575+
childrel->parent,
576+
parentrel);
577+
else
578+
elog(ERROR, "childrel is not a child of parentrel");
596579
}
597580

598-
result = adjust_child_relids(relids, nappinfos, appinfos);
581+
/* Now translate for this child. */
582+
appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
583+
584+
relids = adjust_child_relids(relids, nappinfos, appinfos);
599585

600-
/* Free memory consumed by any intermediate result. */
601-
if (tmp_result)
602-
bms_free(tmp_result);
603-
bms_free(parent_relids);
604586
pfree(appinfos);
605587

606-
return result;
588+
return relids;
607589
}
608590

609591
/*
@@ -694,8 +676,8 @@ get_translated_update_targetlist(PlannerInfo *root, Index relid,
694676
*processed_tlist = (List *)
695677
adjust_appendrel_attrs_multilevel(root,
696678
(Node *) root->processed_tlist,
697-
bms_make_singleton(relid),
698-
bms_make_singleton(root->parse->resultRelation));
679+
find_base_rel(root, relid),
680+
find_base_rel(root, root->parse->resultRelation));
699681
if (update_colnos)
700682
*update_colnos =
701683
adjust_inherited_attnums_multilevel(root, root->update_colnos,

src/backend/optimizer/util/pathnode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4026,8 +4026,8 @@ reparameterize_path_by_child(PlannerInfo *root, Path *path,
40264026
#define ADJUST_CHILD_ATTRS(node) \
40274027
((node) = \
40284028
(List *) adjust_appendrel_attrs_multilevel(root, (Node *) (node), \
4029-
child_rel->relids, \
4030-
child_rel->top_parent_relids))
4029+
child_rel, \
4030+
child_rel->top_parent))
40314031

40324032
#define REPARAMETERIZE_CHILD_PATH(path) \
40334033
do { \
@@ -4244,8 +4244,8 @@ do { \
42444244
old_ppi = new_path->param_info;
42454245
required_outer =
42464246
adjust_child_relids_multilevel(root, old_ppi->ppi_req_outer,
4247-
child_rel->relids,
4248-
child_rel->top_parent_relids);
4247+
child_rel,
4248+
child_rel->top_parent);
42494249

42504250
/* If we already have a PPI for this parameterization, just return it */
42514251
new_ppi = find_param_path_info(new_path->parent, required_outer);

src/backend/optimizer/util/relnode.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,10 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
265265
*/
266266
if (parent)
267267
{
268-
/*
269-
* Each direct or indirect child wants to know the relids of its
270-
* topmost parent.
271-
*/
272-
if (parent->top_parent_relids)
273-
rel->top_parent_relids = parent->top_parent_relids;
274-
else
275-
rel->top_parent_relids = bms_copy(parent->relids);
268+
/* We keep back-links to immediate parent and topmost parent. */
269+
rel->parent = parent;
270+
rel->top_parent = parent->top_parent ? parent->top_parent : parent;
271+
rel->top_parent_relids = rel->top_parent->relids;
276272

277273
/*
278274
* Also propagate lateral-reference information from appendrel parent
@@ -294,6 +290,8 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
294290
}
295291
else
296292
{
293+
rel->parent = NULL;
294+
rel->top_parent = NULL;
297295
rel->top_parent_relids = NULL;
298296
rel->direct_lateral_relids = NULL;
299297
rel->lateral_relids = NULL;
@@ -663,6 +661,8 @@ build_join_rel(PlannerInfo *root,
663661
joinrel->joininfo = NIL;
664662
joinrel->has_eclass_joins = false;
665663
joinrel->consider_partitionwise_join = false; /* might get changed later */
664+
joinrel->parent = NULL;
665+
joinrel->top_parent = NULL;
666666
joinrel->top_parent_relids = NULL;
667667
joinrel->part_scheme = NULL;
668668
joinrel->nparts = -1;
@@ -843,7 +843,9 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
843843
joinrel->joininfo = NIL;
844844
joinrel->has_eclass_joins = false;
845845
joinrel->consider_partitionwise_join = false; /* might get changed later */
846-
joinrel->top_parent_relids = NULL;
846+
joinrel->parent = parent_joinrel;
847+
joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
848+
joinrel->top_parent_relids = joinrel->top_parent->relids;
847849
joinrel->part_scheme = NULL;
848850
joinrel->nparts = -1;
849851
joinrel->boundinfo = NULL;
@@ -855,9 +857,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
855857
joinrel->partexprs = NULL;
856858
joinrel->nullable_partexprs = NULL;
857859

858-
joinrel->top_parent_relids = bms_union(outer_rel->top_parent_relids,
859-
inner_rel->top_parent_relids);
860-
861860
/* Compute information relevant to foreign relations. */
862861
set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
863862

src/backend/partitioning/partprune.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,8 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
529529
partprunequal = (List *)
530530
adjust_appendrel_attrs_multilevel(root,
531531
(Node *) prunequal,
532-
subpart->relids,
533-
targetpart->relids);
532+
subpart,
533+
targetpart);
534534
}
535535

536536
/*

src/include/nodes/pathnodes.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,15 @@ typedef struct RelOptInfo
938938
*/
939939
/* consider partitionwise join paths? (if partitioned rel) */
940940
bool consider_partitionwise_join;
941-
/* Relids of topmost parents (if "other" rel) */
941+
942+
/*
943+
* inheritance links, if this is an otherrel (otherwise NULL):
944+
*/
945+
/* Immediate parent relation (dumping it would be too verbose) */
946+
struct RelOptInfo *parent pg_node_attr(read_write_ignore);
947+
/* Topmost parent relation (dumping it would be too verbose) */
948+
struct RelOptInfo *top_parent pg_node_attr(read_write_ignore);
949+
/* Relids of topmost parent (redundant, but handy) */
942950
Relids top_parent_relids;
943951

944952
/*

src/include/optimizer/appendinfo.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ extern AppendRelInfo *make_append_rel_info(Relation parentrel,
2323
extern Node *adjust_appendrel_attrs(PlannerInfo *root, Node *node,
2424
int nappinfos, AppendRelInfo **appinfos);
2525
extern Node *adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
26-
Relids child_relids,
27-
Relids top_parent_relids);
26+
RelOptInfo *childrel,
27+
RelOptInfo *parentrel);
2828
extern Relids adjust_child_relids(Relids relids, int nappinfos,
2929
AppendRelInfo **appinfos);
3030
extern Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
31-
Relids child_relids,
32-
Relids top_parent_relids);
31+
RelOptInfo *childrel,
32+
RelOptInfo *parentrel);
3333
extern List *adjust_inherited_attnums(List *attnums, AppendRelInfo *context);
3434
extern List *adjust_inherited_attnums_multilevel(PlannerInfo *root,
3535
List *attnums,

0 commit comments

Comments
 (0)