mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03: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:
@@ -45,6 +45,7 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
|
|||||||
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
|
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
|
||||||
SpecialJoinInfo *parent_sjinfo,
|
SpecialJoinInfo *parent_sjinfo,
|
||||||
Relids left_relids, Relids right_relids);
|
Relids left_relids, Relids right_relids);
|
||||||
|
static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo);
|
||||||
static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
|
static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
|
||||||
RelOptInfo *rel2, RelOptInfo *joinrel,
|
RelOptInfo *rel2, RelOptInfo *joinrel,
|
||||||
SpecialJoinInfo *parent_sjinfo,
|
SpecialJoinInfo *parent_sjinfo,
|
||||||
@@ -1659,6 +1660,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
|||||||
child_restrictlist);
|
child_restrictlist);
|
||||||
|
|
||||||
pfree(appinfos);
|
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
|
* Construct the SpecialJoinInfo for a child-join by translating
|
||||||
* SpecialJoinInfo for the join between parents. left_relids and right_relids
|
* SpecialJoinInfo for the join between parents. left_relids and right_relids
|
||||||
* are the relids of left and right side of the join respectively.
|
* 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 *
|
static SpecialJoinInfo *
|
||||||
build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
|
build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
|
||||||
@@ -1705,6 +1710,37 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
|
|||||||
return 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_partition_bounds
|
||||||
* Compute the partition bounds for a join rel from those for inputs
|
* 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;
|
pathnode->subpath = subpath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Under GEQO, the sjinfo might be short-lived, so we'd better make copies
|
* Under GEQO and when planning child joins, the sjinfo might be
|
||||||
* of data structures we extract from it.
|
* short-lived, so we'd better make copies of data structures we extract
|
||||||
|
* from it.
|
||||||
*/
|
*/
|
||||||
pathnode->in_operators = copyObject(sjinfo->semi_operators);
|
pathnode->in_operators = copyObject(sjinfo->semi_operators);
|
||||||
pathnode->uniq_exprs = copyObject(sjinfo->semi_rhs_exprs);
|
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
|
* 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
|
* plain innerjoin semantics. Note that lhs_strict and the semi_xxx fields
|
||||||
* are not set meaningfully within such structs.
|
* 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
|
#ifndef HAVE_SPECIALJOININFO_TYPEDEF
|
||||||
typedef struct SpecialJoinInfo SpecialJoinInfo;
|
typedef struct SpecialJoinInfo SpecialJoinInfo;
|
||||||
|
|||||||
Reference in New Issue
Block a user