Skip to content

Commit 1957f8d

Browse files
committed
Initialize ExprStates once in run-time partition pruning
Instead of doing ExecInitExpr every time a Param needs to be evaluated in run-time partition pruning, do it once during run-time pruning set-up and cache the exprstate in PartitionPruneContext, saving a lot of work. Author: David Rowley Reviewed-by: Amit Langote, Álvaro Herrera Discussion: https://postgr.es/m/CAKJS1f8-x+q-90QAPDu_okhQBV4DPEtPz8CJ=m0940GyT4DA4w@mail.gmail.com
1 parent 055fb8d commit 1957f8d

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed

src/backend/executor/execPartition.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,9 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
14421442
PartitionDesc partdesc;
14431443
Relation rel;
14441444
PartitionKey partkey;
1445+
ListCell *lc2;
14451446
int partnatts;
1447+
int n_steps;
14461448

14471449
pprune->present_parts = bms_copy(pinfo->present_parts);
14481450
pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts);
@@ -1465,6 +1467,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
14651467

14661468
partkey = RelationGetPartitionKey(rel);
14671469
partdesc = RelationGetPartitionDesc(rel);
1470+
n_steps = list_length(pinfo->pruning_steps);
14681471

14691472
context->strategy = partkey->strategy;
14701473
context->partnatts = partnatts = partkey->partnatts;
@@ -1476,6 +1479,38 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
14761479
context->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey);
14771480
context->planstate = planstate;
14781481
context->safeparams = NULL; /* empty for now */
1482+
context->exprstates = palloc0(sizeof(ExprState *) * n_steps * partnatts);
1483+
1484+
/* Initialize expression states for each expression */
1485+
foreach(lc2, pinfo->pruning_steps)
1486+
{
1487+
PartitionPruneStepOp *step = (PartitionPruneStepOp *) lfirst(lc2);
1488+
ListCell *lc3;
1489+
int keyno;
1490+
1491+
/* not needed for other step kinds */
1492+
if (!IsA(step, PartitionPruneStepOp))
1493+
continue;
1494+
1495+
Assert(list_length(step->exprs) <= partnatts);
1496+
1497+
keyno = 0;
1498+
foreach(lc3, step->exprs)
1499+
{
1500+
Expr *expr = (Expr *) lfirst(lc3);
1501+
int stateidx;
1502+
1503+
/* not needed for Consts */
1504+
if (!IsA(expr, Const))
1505+
{
1506+
stateidx = PruneCxtStateIdx(partnatts,
1507+
step->step.step_id, keyno);
1508+
context->exprstates[stateidx] =
1509+
ExecInitExpr(expr, context->planstate);
1510+
}
1511+
keyno++;
1512+
}
1513+
}
14791514

14801515
pprune->pruning_steps = pinfo->pruning_steps;
14811516
pprune->extparams = bms_copy(pinfo->extparams);

src/backend/partitioning/partprune.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
169169
static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
170170
Expr *partkey, Expr **outconst);
171171
static bool partkey_datum_from_expr(PartitionPruneContext *context,
172-
Expr *expr, Datum *value);
172+
Expr *expr, int stateidx, Datum *value);
173173

174174
/*
175175
* make_partition_pruneinfo
@@ -444,6 +444,7 @@ prune_append_rel_partitions(RelOptInfo *rel)
444444
/* Not valid when being called from the planner */
445445
context.planstate = NULL;
446446
context.safeparams = NULL;
447+
context.exprstates = NULL;
447448

448449
/* Actual pruning happens here. */
449450
partindexes = get_matching_partitions(&context, pruning_steps);
@@ -2788,10 +2789,13 @@ perform_pruning_base_step(PartitionPruneContext *context,
27882789
if (lc1 != NULL)
27892790
{
27902791
Expr *expr;
2792+
int stateidx;
27912793
Datum datum;
27922794

27932795
expr = lfirst(lc1);
2794-
if (partkey_datum_from_expr(context, expr, &datum))
2796+
stateidx = PruneCxtStateIdx(context->partnatts,
2797+
opstep->step.step_id, keyno);
2798+
if (partkey_datum_from_expr(context, expr, stateidx, &datum))
27952799
{
27962800
Oid cmpfn;
27972801

@@ -3025,12 +3029,15 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
30253029

30263030
/*
30273031
* partkey_datum_from_expr
3028-
* Evaluate 'expr', set *value to the resulting Datum. Return true if
3029-
* evaluation was possible, otherwise false.
3032+
* Evaluate expression for potential partition pruning
3033+
*
3034+
* Evaluate 'expr', whose ExprState is stateidx of the context exprstate
3035+
* array; set *value to the resulting Datum. Return true if evaluation was
3036+
* possible, otherwise false.
30303037
*/
30313038
static bool
30323039
partkey_datum_from_expr(PartitionPruneContext *context,
3033-
Expr *expr, Datum *value)
3040+
Expr *expr, int stateidx, Datum *value)
30343041
{
30353042
switch (nodeTag(expr))
30363043
{
@@ -3048,18 +3055,18 @@ partkey_datum_from_expr(PartitionPruneContext *context,
30483055
bms_is_member(((Param *) expr)->paramid, context->safeparams))
30493056
{
30503057
ExprState *exprstate;
3058+
ExprContext *ectx;
30513059
bool isNull;
30523060

3053-
exprstate = ExecInitExpr(expr, context->planstate);
3054-
3055-
*value = ExecEvalExprSwitchContext(exprstate,
3056-
context->planstate->ps_ExprContext,
3057-
&isNull);
3061+
exprstate = context->exprstates[stateidx];
3062+
ectx = context->planstate->ps_ExprContext;
3063+
*value = ExecEvalExprSwitchContext(exprstate, ectx, &isNull);
30583064
if (isNull)
30593065
return false;
30603066

30613067
return true;
30623068
}
3069+
break;
30633070

30643071
default:
30653072
break;

src/include/partitioning/partprune.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,17 @@ typedef struct PartitionPruneContext
5050
* are not safe to use until the executor is running.
5151
*/
5252
Bitmapset *safeparams;
53+
54+
/*
55+
* Array of ExprStates, indexed as per PruneCtxStateIdx; one for each
56+
* partkey in each pruning step. Allocated if planstate is non-NULL,
57+
* otherwise NULL.
58+
*/
59+
ExprState **exprstates;
5360
} PartitionPruneContext;
5461

62+
#define PruneCxtStateIdx(partnatts, step_id, keyno) \
63+
((partnatts) * (step_id) + (keyno))
5564

5665
extern List *make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
5766
List *subpaths, List *prunequal);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy