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

Commit 8d8dcea

Browse files
author
Etsuro Fujita
committed
Postpone generating tlists and EC members for inheritance dummy children.
Previously, in set_append_rel_size(), we generated tlists and EC members for dummy children for possible use by partition-wise join, even if partition-wise join was disabled or the top parent was not a partitioned table, but adding such EC members causes noticeable planning speed degradation for queries with certain kinds of join quals like "(foo.x + bar.y) = constant" where foo and bar are partitioned tables in cases where there are lots of dummy children, as the EC members lists grow huge, especially for the ECs derived from such join quals, which makes the search for the parent EC members in add_child_rel_equivalences() very time-consuming. Postpone the work until such children are actually involved in a partition-wise join. Reported-by: Sanyo Capobiango Analyzed-by: Justin Pryzby and Alvaro Herrera Author: Amit Langote, with a few additional changes by me Reviewed-by: Ashutosh Bapat Backpatch-through: v11 where partition-wise join was added Discussion: https://postgr.es/m/CAO698qZnrxoZu7MEtfiJmpmUtz3AVYFVnwzR%2BpqjF%3DrmKBTgpw%40mail.gmail.com
1 parent 31f3817 commit 8d8dcea

File tree

2 files changed

+86
-39
lines changed

2 files changed

+86
-39
lines changed

src/backend/optimizer/path/allpaths.c

+39-39
Original file line numberDiff line numberDiff line change
@@ -1018,42 +1018,11 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10181018
Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
10191019

10201020
/*
1021-
* Copy/Modify targetlist. Even if this child is deemed empty, we need
1022-
* its targetlist in case it falls on nullable side in a child-join
1023-
* because of partitionwise join.
1024-
*
1025-
* NB: the resulting childrel->reltarget->exprs may contain arbitrary
1026-
* expressions, which otherwise would not occur in a rel's targetlist.
1027-
* Code that might be looking at an appendrel child must cope with
1028-
* such. (Normally, a rel's targetlist would only include Vars and
1029-
* PlaceHolderVars.) XXX we do not bother to update the cost or width
1030-
* fields of childrel->reltarget; not clear if that would be useful.
1031-
*/
1032-
childrel->reltarget->exprs = (List *)
1033-
adjust_appendrel_attrs(root,
1034-
(Node *) rel->reltarget->exprs,
1035-
1, &appinfo);
1036-
1037-
/*
1038-
* We have to make child entries in the EquivalenceClass data
1039-
* structures as well. This is needed either if the parent
1040-
* participates in some eclass joins (because we will want to consider
1041-
* inner-indexscan joins on the individual children) or if the parent
1042-
* has useful pathkeys (because we should try to build MergeAppend
1043-
* paths that produce those sort orderings). Even if this child is
1044-
* deemed dummy, it may fall on nullable side in a child-join, which
1045-
* in turn may participate in a MergeAppend, where we will need the
1046-
* EquivalenceClass data structures.
1047-
*/
1048-
if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
1049-
add_child_rel_equivalences(root, appinfo, rel, childrel);
1050-
childrel->has_eclass_joins = rel->has_eclass_joins;
1051-
1052-
/*
1053-
* We have to copy the parent's quals to the child, with appropriate
1054-
* substitution of variables. However, only the baserestrictinfo
1055-
* quals are needed before we can check for constraint exclusion; so
1056-
* do that first and then check to see if we can disregard this child.
1021+
* We have to copy the parent's targetlist and quals to the child,
1022+
* with appropriate substitution of variables. However, only the
1023+
* baserestrictinfo quals are needed before we can check for
1024+
* constraint exclusion; so do that first and then check to see if we
1025+
* can disregard this child.
10571026
*
10581027
* The child rel's targetlist might contain non-Var expressions, which
10591028
* means that substitution into the quals could produce opportunities
@@ -1187,11 +1156,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
11871156
continue;
11881157
}
11891158

1190-
/* CE failed, so finish copying/modifying join quals. */
1159+
/*
1160+
* CE failed, so finish copying/modifying targetlist and join quals.
1161+
*
1162+
* NB: the resulting childrel->reltarget->exprs may contain arbitrary
1163+
* expressions, which otherwise would not occur in a rel's targetlist.
1164+
* Code that might be looking at an appendrel child must cope with
1165+
* such. (Normally, a rel's targetlist would only include Vars and
1166+
* PlaceHolderVars.) XXX we do not bother to update the cost or width
1167+
* fields of childrel->reltarget; not clear if that would be useful.
1168+
*/
11911169
childrel->joininfo = (List *)
11921170
adjust_appendrel_attrs(root,
11931171
(Node *) rel->joininfo,
11941172
1, &appinfo);
1173+
childrel->reltarget->exprs = (List *)
1174+
adjust_appendrel_attrs(root,
1175+
(Node *) rel->reltarget->exprs,
1176+
1, &appinfo);
1177+
1178+
/*
1179+
* We have to make child entries in the EquivalenceClass data
1180+
* structures as well. This is needed either if the parent
1181+
* participates in some eclass joins (because we will want to consider
1182+
* inner-indexscan joins on the individual children) or if the parent
1183+
* has useful pathkeys (because we should try to build MergeAppend
1184+
* paths that produce those sort orderings).
1185+
*/
1186+
if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
1187+
add_child_rel_equivalences(root, appinfo, rel, childrel);
1188+
childrel->has_eclass_joins = rel->has_eclass_joins;
11951189

11961190
/*
11971191
* Note: we could compute appropriate attr_needed data for the child's
@@ -1204,9 +1198,15 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
12041198
/*
12051199
* If we consider partitionwise joins with the parent rel, do the same
12061200
* for partitioned child rels.
1201+
*
1202+
* Note: here we abuse the consider_partitionwise_join flag by setting
1203+
* it *even* for child rels that are not partitioned. In that case,
1204+
* we set it to tell try_partitionwise_join() that it doesn't need to
1205+
* generate their targetlists and EC entries as they have already been
1206+
* generated here, as opposed to the dummy child rels for which the
1207+
* flag is left set to false so that it will generate them.
12071208
*/
1208-
if (rel->consider_partitionwise_join &&
1209-
childRTE->relkind == RELKIND_PARTITIONED_TABLE)
1209+
if (rel->consider_partitionwise_join)
12101210
childrel->consider_partitionwise_join = true;
12111211

12121212
/*

src/backend/optimizer/path/joinrels.c

+47
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
4444
RelOptInfo *rel2, RelOptInfo *joinrel,
4545
SpecialJoinInfo *parent_sjinfo,
4646
List *parent_restrictlist);
47+
static void update_child_rel_info(PlannerInfo *root,
48+
RelOptInfo *rel, RelOptInfo *childrel);
4749
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
4850
SpecialJoinInfo *parent_sjinfo,
4951
Relids left_relids, Relids right_relids);
@@ -1315,6 +1317,8 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
13151317
RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo,
13161318
List *parent_restrictlist)
13171319
{
1320+
bool rel1_is_simple = IS_SIMPLE_REL(rel1);
1321+
bool rel2_is_simple = IS_SIMPLE_REL(rel2);
13181322
int nparts;
13191323
int cnt_parts;
13201324

@@ -1379,6 +1383,27 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
13791383
AppendRelInfo **appinfos;
13801384
int nappinfos;
13811385

1386+
/*
1387+
* If a child table has consider_partitionwise_join=false, it means
1388+
* that it's a dummy relation for which we skipped setting up tlist
1389+
* expressions and adding EC members in set_append_rel_size(), so do
1390+
* that now for use later.
1391+
*/
1392+
if (rel1_is_simple && !child_rel1->consider_partitionwise_join)
1393+
{
1394+
Assert(child_rel1->reloptkind == RELOPT_OTHER_MEMBER_REL);
1395+
Assert(IS_DUMMY_REL(child_rel1));
1396+
update_child_rel_info(root, rel1, child_rel1);
1397+
child_rel1->consider_partitionwise_join = true;
1398+
}
1399+
if (rel2_is_simple && !child_rel2->consider_partitionwise_join)
1400+
{
1401+
Assert(child_rel2->reloptkind == RELOPT_OTHER_MEMBER_REL);
1402+
Assert(IS_DUMMY_REL(child_rel2));
1403+
update_child_rel_info(root, rel2, child_rel2);
1404+
child_rel2->consider_partitionwise_join = true;
1405+
}
1406+
13821407
/* We should never try to join two overlapping sets of rels. */
13831408
Assert(!bms_overlap(child_rel1->relids, child_rel2->relids));
13841409
child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids);
@@ -1420,6 +1445,28 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
14201445
}
14211446
}
14221447

1448+
/*
1449+
* Set up tlist expressions for the childrel, and add EC members referencing
1450+
* the childrel.
1451+
*/
1452+
static void
1453+
update_child_rel_info(PlannerInfo *root,
1454+
RelOptInfo *rel, RelOptInfo *childrel)
1455+
{
1456+
AppendRelInfo *appinfo = root->append_rel_array[childrel->relid];
1457+
1458+
/* Make child tlist expressions */
1459+
childrel->reltarget->exprs = (List *)
1460+
adjust_appendrel_attrs(root,
1461+
(Node *) rel->reltarget->exprs,
1462+
1, &appinfo);
1463+
1464+
/* Make child entries in the EquivalenceClass as well */
1465+
if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
1466+
add_child_rel_equivalences(root, appinfo, rel, childrel);
1467+
childrel->has_eclass_joins = rel->has_eclass_joins;
1468+
}
1469+
14231470
/*
14241471
* Construct the SpecialJoinInfo for a child-join by translating
14251472
* SpecialJoinInfo for the join between parents. left_relids and right_relids

0 commit comments

Comments
 (0)