8000 Reduce memory used by partitionwise joins · postgres/postgres@5278d0a · GitHub
[go: up one dir, main page]

Skip to content

Commit 5278d0a

Browse files
committed
Reduce memory used by partitionwise joins
Specifically, this commit reduces the memory consumed by the SpecialJoinInfos that are allocated for child joins in try_partitionwise_join() by freeing them at the end of creating paths for each child join. A SpecialJoinInfo allocated for a given child join is a copy of the parent join's SpecialJoinInfo, which contains the translated copies of the various Relids bitmapsets and semi_rhs_exprs, which is a List of Nodes. The newly added freeing step frees the struct itself and the various bitmapsets, but not semi_rhs_exprs, because there's no handy function to free the memory of Node trees. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Reviewed-by: Richard Guo <guofenglinux@gmail.com> Reviewed-by: Amit Langote <amitlangote09@gmail.com> Reviewed-by: Andrey Lepikhov <a.lepikhov@postgrespro.ru> Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com> Discussion: https://postgr.es/m/CAExHW5tHqEf3ASVqvFFcghYGPfpy7o3xnvhHwBGbJFMRH8KjNw@mail.gmail.com
1 parent 619bc23 commit 5278d0a

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

src/backend/optimizer/path/joinrels.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
4545
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
4646
SpecialJoinInfo *parent_sjinfo,
4747
Relids left_relids, Relids right_relids);
48+
static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo);
4849
static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
4950
RelOptInfo *rel2, RelOptInfo *joinrel,
5051
SpecialJoinInfo *parent_sjinfo,
@@ -1659,13 +1660,17 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
16591660
child_restrictlist);
16601661

16611662
pfree(appinfos);
1663+
free_child_join_sjinfo(child_sjinfo);
16621664
}
16631665
}
16641666

16651667
/*
16661668
* Construct the SpecialJoinInfo for a child-join by translating
16671669
* SpecialJoinInfo for the join between parents. left_relids and right_relids
16681670
* are the relids of left and right side of the join respectively.
1671+
*
1672+
* If translations are added to or removed from this function, consider
1673+
* updating free_child_join_sjinfo() accordingly.
16691674
*/
16701675
static SpecialJoinInfo *
16711676
build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
@@ -1705,6 +1710,37 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
17051710
return sjinfo;
17061711
}
17071712

1713+
/*
1714+
* free_child_join_sjinfo
1715+
* Free memory consumed by a SpecialJoinInfo created by
1716+
* build_child_join_sjinfo()
1717+
*
1718+
* Only members that are translated copies of their counterpart in the parent
1719+
* SpecialJoinInfo are freed here.
1720+
*/
1721+
static void
1722+
free_child_join_sjinfo(SpecialJoinInfo *sjinfo)
1723+
{
1724+
/*
1725+
* Dummy SpecialJoinInfos of inner joins do not have any translated fields
1726+
* and hence no fields that to be freed.
1727+
*/
1728+
if (sjinfo->jointype != JOIN_INNER)
1729+
{
1730+
bms_free(sjinfo->min_lefthand);
1731+
bms_free(sjinfo->min_righthand);
1732+
bms_free(sjinfo->syn_lefthand);
1733+
bms_free(sjinfo->syn_righthand);
1734+
1735+
/*
1736+
* semi_rhs_exprs may in principle be freed, but a simple pfree() does
1737+
* not suffice, so we leave it alone.
1738+
*/
1739+
}
1740+
1741+
pfree(sjinfo);
1742+
}
1743+
17081744
/*
17091745
* compute_partition_bounds
17101746
* Compute the partition bounds for a join rel from those for inputs

src/backend/optimizer/util/pathnode.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,8 +1707,9 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
17071707
pathnode->subpath = subpath;
17081708

17091709
/*
1710-
* Under GEQO, the sjinfo might be short-lived, so we'd better make copies
1711-
* of data structures we extract from it.
1710+
* Under GEQO and when planning child joins, the sjinfo might be
1711+
* short-lived, so we'd better make copies of data structures we extract
1712+
* from it.
17121713
*/
17131714
pathnode->in_operators = copyObject(sjinfo->semi_operators);
17141715
pathnode->uniq_exprs = copyObject(sjinfo->semi_rhs_exprs);

src/include/nodes/pathnodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,6 +2856,9 @@ typedef struct PlaceHolderVar
28562856
* cost estimation purposes it is sometimes useful to know the join size under
28572857
* plain innerjoin semantics. Note that lhs_strict and the semi_xxx fields
28582858
* are not set meaningfully within such structs.
2859+
*
2860+
* We also create transient SpecialJoinInfos for child joins during
2861+
* partiotionwise join planning, which are also not present in join_info_list.
28592862
*/
28602863
#ifndef HAVE_SPECIALJOININFO_TYPEDEF
28612864
typedef struct SpecialJoinInfo SpecialJoinInfo;

0 commit comments

Comments
 (0)
0