v1-estimate-selectivities-in-temp-context.patch
text/x-diff
Filename: v1-estimate-selectivities-in-temp-context.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/clausesel.c | 23 | 0 |
| src/backend/optimizer/plan/planner.c | 27 | 0 |
| src/backend/optimizer/prep/prepjointree.c | 4 | 1 |
| src/include/nodes/pathnodes.h | 5 | 0 |
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index c949dc1866..669acd7315 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -24,6 +24,7 @@
#include "statistics/statistics.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
#include "utils/selfuncs.h"
/*
@@ -693,6 +694,7 @@ clause_selectivity_ext(PlannerInfo *root,
Selectivity s1 = 0.5; /* default for any unhandled clause type */
RestrictInfo *rinfo = NULL;
bool cacheable = false;
+ MemoryContext saved_cxt;
if (clause == NULL) /* can this still happen? */
return s1;
@@ -756,6 +758,21 @@ clause_selectivity_ext(PlannerInfo *root,
clause = (Node *) rinfo->clause;
}
+ /*
+ * Run all the remaining work in the short-lived planner_tmp_cxt, which
+ * we'll reset at the bottom. This allows selectivity-related code to not
+ * be too concerned about leaking memory.
+ */
+ saved_cxt = MemoryContextSwitchTo(root->planner_tmp_cxt);
+
+ /*
+ * This function can be called recursively, in which case we'd better not
+ * reset planner_tmp_cxt until we exit the topmost level. Use of
+ * planner_tmp_cxt_depth also makes it safe for other places to use and
+ * reset planner_tmp_cxt in the same fashion.
+ */
+ root->planner_tmp_cxt_depth++;
+
if (IsA(clause, Var))
{
Var *var = (Var *) clause;
@@ -967,6 +984,12 @@ clause_selectivity_ext(PlannerInfo *root,
rinfo->outer_selec = s1;
}
+ /* Exit and clean up the planner_tmp_cxt */
+ MemoryContextSwitchTo(saved_cxt);
+ Assert(root->planner_tmp_cxt_depth > 0);
+ if (--root->planner_tmp_cxt_depth == 0)
+ MemoryContextReset(root->planner_tmp_cxt);
+
#ifdef SELECTIVITY_DEBUG
elog(DEBUG4, "clause_selectivity: s1 %f", s1);
#endif /* SELECTIVITY_DEBUG */
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index be4e182869..44b9555dbf 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -643,6 +643,17 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->plan_params = NIL;
root->outer_params = NULL;
root->planner_cxt = CurrentMemoryContext;
+ /* a subquery can share the main query's planner_tmp_cxt */
+ if (parent_root)
+ {
+ root->planner_tmp_cxt = parent_root->planner_tmp_cxt;
+ Assert(parent_root->planner_tmp_cxt_depth == 0);
+ }
+ else
+ root->planner_tmp_cxt = AllocSetContextCreate(root->planner_cxt,
+ "Planner temp context",
+ ALLOCSET_DEFAULT_SIZES);
+ root->planner_tmp_cxt_depth = 0;
root->init_plans = NIL;
root->cte_plan_ids = NIL;
root->multiexpr_params = NIL;
@@ -6514,6 +6525,10 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
root->glob = glob;
root->query_level = 1;
root->planner_cxt = CurrentMemoryContext;
+ root->planner_tmp_cxt = AllocSetContextCreate(root->planner_cxt,
+ "Planner temp context",
+ ALLOCSET_DEFAULT_SIZES);
+ root->planner_tmp_cxt_depth = 0;
root->wt_param_id = -1;
root->join_domains = list_make1(makeNode(JoinDomain));
@@ -6552,7 +6567,10 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
* trust the index contents but use seqscan-and-sort.
*/
if (lc == NULL) /* not in the list? */
+ {
+ MemoryContextDelete(root->planner_tmp_cxt);
return true; /* use sort */
+ }
/*
* Rather than doing all the pushups that would be needed to use
@@ -6584,6 +6602,9 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
ForwardScanDirection, false,
NULL, 1.0, false);
+ /* We assume this won't free *indexScanPath */
+ MemoryContextDelete(root->planner_tmp_cxt);
+
return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
}
@@ -6636,6 +6657,10 @@ plan_create_index_workers(Oid tableOid, Oid indexOid)
root->glob = glob;
root->query_level = 1;
root->planner_cxt = CurrentMemoryContext;
+ root->planner_tmp_cxt = AllocSetContextCreate(root->planner_cxt,
+ "Planner temp context",
+ ALLOCSET_DEFAULT_SIZES);
+ root->planner_tmp_cxt_depth = 0;
root->wt_param_id = -1;
root->join_domains = list_make1(makeNode(JoinDomain));
@@ -6725,6 +6750,8 @@ plan_create_index_workers(Oid tableOid, Oid indexOid)
parallel_workers--;
done:
+ MemoryContextDelete(root->planner_tmp_cxt);
+
index_close(index, NoLock);
table_close(heap, NoLock);
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index aa83dd3636..0ea8361190 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -987,7 +987,10 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
subroot->parent_root = root->parent_root;
subroot->plan_params = NIL;
subroot->outer_params = NULL;
- subroot->planner_cxt = CurrentMemoryContext;
+ subroot->planner_cxt = root->planner_cxt;
+ subroot->planner_tmp_cxt = root->planner_tmp_cxt;
+ Assert(root->planner_tmp_cxt_depth == 0);
+ subroot->planner_tmp_cxt_depth = 0;
subroot->init_plans = NIL;
subroot->cte_plan_ids = NIL;
subroot->multiexpr_params = NIL;
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 534692bee1..d278a9773a 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -471,6 +471,11 @@ struct PlannerInfo
/* context holding PlannerInfo */
MemoryContext planner_cxt pg_node_attr(read_write_ignore);
+ /* short-lived context for purposes such as calling selectivity functions */
+ MemoryContext planner_tmp_cxt pg_node_attr(read_write_ignore);
+ /* nesting depth of uses of planner_tmp_cxt; reset it only at level 0 */
+ int planner_tmp_cxt_depth;
+
/* # of pages in all non-dummy tables of query */
Cardinality total_table_pages;