mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
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
This commit is contained in:
parent
055fb8d33d
commit
1957f8dabf
@ -1442,7 +1442,9 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
|
|||||||
PartitionDesc partdesc;
|
PartitionDesc partdesc;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
PartitionKey partkey;
|
PartitionKey partkey;
|
||||||
|
ListCell *lc2;
|
||||||
int partnatts;
|
int partnatts;
|
||||||
|
int n_steps;
|
||||||
|
|
||||||
pprune->present_parts = bms_copy(pinfo->present_parts);
|
pprune->present_parts = bms_copy(pinfo->present_parts);
|
||||||
pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts);
|
pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts);
|
||||||
@ -1465,6 +1467,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
|
|||||||
|
|
||||||
partkey = RelationGetPartitionKey(rel);
|
partkey = RelationGetPartitionKey(rel);
|
||||||
partdesc = RelationGetPartitionDesc(rel);
|
partdesc = RelationGetPartitionDesc(rel);
|
||||||
|
n_steps = list_length(pinfo->pruning_steps);
|
||||||
|
|
||||||
context->strategy = partkey->strategy;
|
context->strategy = partkey->strategy;
|
||||||
context->partnatts = partnatts = partkey->partnatts;
|
context->partnatts = partnatts = partkey->partnatts;
|
||||||
@ -1476,6 +1479,38 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
|
|||||||
context->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey);
|
context->boundinfo = partition_bounds_copy(partdesc->boundinfo, partkey);
|
||||||
context->planstate = planstate;
|
context->planstate = planstate;
|
||||||
context->safeparams = NULL; /* empty for now */
|
context->safeparams = NULL; /* empty for now */
|
||||||
|
context->exprstates = palloc0(sizeof(ExprState *) * n_steps * partnatts);
|
||||||
|
|
||||||
|
/* Initialize expression states for each expression */
|
||||||
|
foreach(lc2, pinfo->pruning_steps)
|
||||||
|
{
|
||||||
|
PartitionPruneStepOp *step = (PartitionPruneStepOp *) lfirst(lc2);
|
||||||
|
ListCell *lc3;
|
||||||
|
int keyno;
|
||||||
|
|
||||||
|
/* not needed for other step kinds */
|
||||||
|
if (!IsA(step, PartitionPruneStepOp))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Assert(list_length(step->exprs) <= partnatts);
|
||||||
|
|
||||||
|
keyno = 0;
|
||||||
|
foreach(lc3, step->exprs)
|
||||||
|
{
|
||||||
|
Expr *expr = (Expr *) lfirst(lc3);
|
||||||
|
int stateidx;
|
||||||
|
|
||||||
|
/* not needed for Consts */
|
||||||
|
if (!IsA(expr, Const))
|
||||||
|
{
|
||||||
|
stateidx = PruneCxtStateIdx(partnatts,
|
||||||
|
step->step.step_id, keyno);
|
||||||
|
context->exprstates[stateidx] =
|
||||||
|
ExecInitExpr(expr, context->planstate);
|
||||||
|
}
|
||||||
|
keyno++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pprune->pruning_steps = pinfo->pruning_steps;
|
pprune->pruning_steps = pinfo->pruning_steps;
|
||||||
pprune->extparams = bms_copy(pinfo->extparams);
|
pprune->extparams = bms_copy(pinfo->extparams);
|
||||||
|
@ -169,7 +169,7 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
|
|||||||
static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
|
static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
|
||||||
Expr *partkey, Expr **outconst);
|
Expr *partkey, Expr **outconst);
|
||||||
static bool partkey_datum_from_expr(PartitionPruneContext *context,
|
static bool partkey_datum_from_expr(PartitionPruneContext *context,
|
||||||
Expr *expr, Datum *value);
|
Expr *expr, int stateidx, Datum *value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make_partition_pruneinfo
|
* make_partition_pruneinfo
|
||||||
@ -444,6 +444,7 @@ prune_append_rel_partitions(RelOptInfo *rel)
|
|||||||
/* Not valid when being called from the planner */
|
/* Not valid when being called from the planner */
|
||||||
context.planstate = NULL;
|
context.planstate = NULL;
|
||||||
context.safeparams = NULL;
|
context.safeparams = NULL;
|
||||||
|
context.exprstates = NULL;
|
||||||
|
|
||||||
/* Actual pruning happens here. */
|
/* Actual pruning happens here. */
|
||||||
partindexes = get_matching_partitions(&context, pruning_steps);
|
partindexes = get_matching_partitions(&context, pruning_steps);
|
||||||
@ -2788,10 +2789,13 @@ perform_pruning_base_step(PartitionPruneContext *context,
|
|||||||
if (lc1 != NULL)
|
if (lc1 != NULL)
|
||||||
{
|
{
|
||||||
Expr *expr;
|
Expr *expr;
|
||||||
|
int stateidx;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
|
|
||||||
expr = lfirst(lc1);
|
expr = lfirst(lc1);
|
||||||
if (partkey_datum_from_expr(context, expr, &datum))
|
stateidx = PruneCxtStateIdx(context->partnatts,
|
||||||
|
opstep->step.step_id, keyno);
|
||||||
|
if (partkey_datum_from_expr(context, expr, stateidx, &datum))
|
||||||
{
|
{
|
||||||
Oid cmpfn;
|
Oid cmpfn;
|
||||||
|
|
||||||
@ -3025,12 +3029,15 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* partkey_datum_from_expr
|
* partkey_datum_from_expr
|
||||||
* Evaluate 'expr', set *value to the resulting Datum. Return true if
|
* Evaluate expression for potential partition pruning
|
||||||
* evaluation was possible, otherwise false.
|
*
|
||||||
|
* Evaluate 'expr', whose ExprState is stateidx of the context exprstate
|
||||||
|
* array; set *value to the resulting Datum. Return true if evaluation was
|
||||||
|
* possible, otherwise false.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
partkey_datum_from_expr(PartitionPruneContext *context,
|
partkey_datum_from_expr(PartitionPruneContext *context,
|
||||||
Expr *expr, Datum *value)
|
Expr *expr, int stateidx, Datum *value)
|
||||||
{
|
{
|
||||||
switch (nodeTag(expr))
|
switch (nodeTag(expr))
|
||||||
{
|
{
|
||||||
@ -3048,18 +3055,18 @@ partkey_datum_from_expr(PartitionPruneContext *context,
|
|||||||
bms_is_member(((Param *) expr)->paramid, context->safeparams))
|
bms_is_member(((Param *) expr)->paramid, context->safeparams))
|
||||||
{
|
{
|
||||||
ExprState *exprstate;
|
ExprState *exprstate;
|
||||||
|
ExprContext *ectx;
|
||||||
bool isNull;
|
bool isNull;
|
||||||
|
|
||||||
exprstate = ExecInitExpr(expr, context->planstate);
|
exprstate = context->exprstates[stateidx];
|
||||||
|
ectx = context->planstate->ps_ExprContext;
|
||||||
*value = ExecEvalExprSwitchContext(exprstate,
|
*value = ExecEvalExprSwitchContext(exprstate, ectx, &isNull);
|
||||||
context->planstate->ps_ExprContext,
|
|
||||||
&isNull);
|
|
||||||
if (isNull)
|
if (isNull)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -50,8 +50,17 @@ typedef struct PartitionPruneContext
|
|||||||
* are not safe to use until the executor is running.
|
* are not safe to use until the executor is running.
|
||||||
*/
|
*/
|
||||||
Bitmapset *safeparams;
|
Bitmapset *safeparams;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Array of ExprStates, indexed as per PruneCtxStateIdx; one for each
|
||||||
|
* partkey in each pruning step. Allocated if planstate is non-NULL,
|
||||||
|
* otherwise NULL.
|
||||||
|
*/
|
||||||
|
ExprState **exprstates;
|
||||||
} PartitionPruneContext;
|
} PartitionPruneContext;
|
||||||
|
|
||||||
|
#define PruneCxtStateIdx(partnatts, step_id, keyno) \
|
||||||
|
((partnatts) * (step_id) + (keyno))
|
||||||
|
|
||||||
extern List *make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
|
extern List *make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
|
||||||
List *subpaths, List *prunequal);
|
List *subpaths, List *prunequal);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user