mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-11-27 07:21:09 +08:00
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
This commit is contained in:
parent
619bc23a1a
commit
5278d0a2e8
@ -45,6 +45,7 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
|
||||
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
|
||||
SpecialJoinInfo *parent_sjinfo,
|
||||
Relids left_relids, Relids right_relids);
|
||||
static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo);
|
||||
static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
|
||||
RelOptInfo *rel2, RelOptInfo *joinrel,
|
||||
SpecialJoinInfo *parent_sjinfo,
|
||||
@ -1659,6 +1660,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
child_restrictlist);
|
||||
|
||||
pfree(appinfos);
|
||||
free_child_join_sjinfo(child_sjinfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1666,6 +1668,9 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
* Construct the SpecialJoinInfo for a child-join by translating
|
||||
* SpecialJoinInfo for the join between parents. left_relids and right_relids
|
||||
* are the relids of left and right side of the join respectively.
|
||||
*
|
||||
* If translations are added to or removed from this function, consider
|
||||
* updating free_child_join_sjinfo() accordingly.
|
||||
*/
|
||||
static SpecialJoinInfo *
|
||||
build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
|
||||
@ -1705,6 +1710,37 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
|
||||
return sjinfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* free_child_join_sjinfo
|
||||
* Free memory consumed by a SpecialJoinInfo created by
|
||||
* build_child_join_sjinfo()
|
||||
*
|
||||
* Only members that are translated copies of their counterpart in the parent
|
||||
* SpecialJoinInfo are freed here.
|
||||
*/
|
||||
static void
|
||||
free_child_join_sjinfo(SpecialJoinInfo *sjinfo)
|
||||
{
|
||||
/*
|
||||
* Dummy SpecialJoinInfos of inner joins do not have any translated fields
|
||||
* and hence no fields that to be freed.
|
||||
*/
|
||||
if (sjinfo->jointype != JOIN_INNER)
|
||||
{
|
||||
bms_free(sjinfo->min_lefthand);
|
||||
bms_free(sjinfo->min_righthand);
|
||||
bms_free(sjinfo->syn_lefthand);
|
||||
bms_free(sjinfo->syn_righthand);
|
||||
|
||||
/*
|
||||
* semi_rhs_exprs may in principle be freed, but a simple pfree() does
|
||||
* not suffice, so we leave it alone.
|
||||
*/
|
||||
}
|
||||
|
||||
pfree(sjinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* compute_partition_bounds
|
||||
* Compute the partition bounds for a join rel from those for inputs
|
||||
|
@ -1707,8 +1707,9 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
|
||||
pathnode->subpath = subpath;
|
||||
|
||||
/*
|
||||
* Under GEQO, the sjinfo might be short-lived, so we'd better make copies
|
||||
* of data structures we extract from it.
|
||||
* Under GEQO and when planning child joins, the sjinfo might be
|
||||
* short-lived, so we'd better make copies of data structures we extract
|
||||
* from it.
|
||||
*/
|
||||
pathnode->in_operators = copyObject(sjinfo->semi_operators);
|
||||
pathnode->uniq_exprs = copyObject(sjinfo->semi_rhs_exprs);
|
||||
|
@ -2856,6 +2856,9 @@ typedef struct PlaceHolderVar
|
||||
* cost estimation purposes it is sometimes useful to know the join size under
|
||||
* plain innerjoin semantics. Note that lhs_strict and the semi_xxx fields
|
||||
* are not set meaningfully within such structs.
|
||||
*
|
||||
* We also create transient SpecialJoinInfos for child joins during
|
||||
* partiotionwise join planning, which are also not present in join_info_list.
|
||||
*/
|
||||
#ifndef HAVE_SPECIALJOININFO_TYPEDEF
|
||||
typedef struct SpecialJoinInfo SpecialJoinInfo;
|
||||
|
Loading…
Reference in New Issue
Block a user