From 67d051526138b00b7429996655a403535ea6d75c Mon Sep 17 00:00:00 2001 From: amit Date: Thu, 6 Dec 2018 10:38:25 +0900 Subject: [PATCH] Add child EC members for only the non-dummy children In set_append_rel_size, child EC members are added before checking if the child relation itself is dummy. That's very inefficient if there are lots of children as the EC lists grow huge. Such EC members would remain unused unless the child participates in partitionwise join, so add them only if the child "actually" participates in partitionwise join. --- src/backend/optimizer/path/allpaths.c | 27 ++++++++++++--------------- src/backend/optimizer/path/joinrels.c | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 738bb30848..2b5fef2233 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1034,21 +1034,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, 1, &appinfo); /* - * We have to make child entries in the EquivalenceClass data - * structures as well. This is needed either if the parent - * participates in some eclass joins (because we will want to consider - * inner-indexscan joins on the individual children) or if the parent - * has useful pathkeys (because we should try to build MergeAppend - * paths that produce those sort orderings). Even if this child is - * deemed dummy, it may fall on nullable side in a child-join, which - * in turn may participate in a MergeAppend, where we will need the - * EquivalenceClass data structures. - */ - if (rel->has_eclass_joins || has_useful_pathkeys(root, rel)) - add_child_rel_equivalences(root, appinfo, rel, childrel); - childrel->has_eclass_joins = rel->has_eclass_joins; - - /* * We have to copy the parent's quals to the child, with appropriate * substitution of variables. However, only the baserestrictinfo * quals are needed before we can check for constraint exclusion; so @@ -1186,6 +1171,18 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, continue; } + /* + * We have to make child entries in the EquivalenceClass data + * structures as well. This is needed either if the parent + * participates in some eclass joins (because we will want to consider + * inner-indexscan joins on the individual children) or if the parent + * has useful pathkeys (because we should try to build MergeAppend + * paths that produce those sort orderings). + */ + if (rel->has_eclass_joins || has_useful_pathkeys(root, rel)) + add_child_rel_equivalences(root, appinfo, rel, childrel); + childrel->has_eclass_joins = rel->has_eclass_joins; + /* CE failed, so finish copying/modifying join quals. */ childrel->joininfo = (List *) adjust_appendrel_attrs(root, diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index d3d21fed5d..631468491c 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -1376,6 +1376,25 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, AppendRelInfo **appinfos; int nappinfos; + /* + * set_append_rel_size() doesn't add EC members for dummy child + * relations. Do that now, because downstream code relies on child + * EC members having been added. + */ + if (IS_SIMPLE_REL(child_rel1) && IS_DUMMY_REL(child_rel1)) + { + AppendRelInfo *appinfo = root->append_rel_array[child_rel1->relid]; + + add_child_rel_equivalences(root, appinfo, rel1, child_rel1); + } + + if (IS_SIMPLE_REL(child_rel2) && IS_DUMMY_REL(child_rel2)) + { + AppendRelInfo *appinfo = root->append_rel_array[child_rel2->relid]; + + add_child_rel_equivalences(root, appinfo, rel2, child_rel2); + } + /* We should never try to join two overlapping sets of rels. */ Assert(!bms_overlap(child_rel1->relids, child_rel2->relids)); child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids); -- 2.11.0