mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Expression evaluation based aggregate transition invocation.
Previously aggregate transition and combination functions were invoked by special case code in nodeAgg.c, evaluating input and filters separately using the expression evaluation machinery. That turns out to not be great for performance for several reasons: - repeated expression evaluations have some cost - the transition functions invocations are poorly predicted, as commonly there are multiple aggregates in a query, resulting in the same call-stack invoking different functions. - filter and input computation had to be done separately - the special case code made it hard to implement JITing of the whole transition function invocation Address this by building one large expression that computes input, evaluates filters, and invokes transition functions. This leads to moderate speedups in queries bottlenecked by aggregate computations, and enables large speedups for similar cases once JITing is done. There's potential for further improvement: - It'd be nice if we could simplify the somewhat expensive aggstate->all_pergroups lookups. - right now there's still an advance_transition_function invocation in nodeAgg.c, leading to some code duplication. Author: Andres Freund Discussion: https://postgr.es/m/20170901064131.tazjxwus3k2w3ybh@alap3.anarazel.de
This commit is contained in:
@ -14,6 +14,7 @@
|
||||
#ifndef EXEC_EXPR_H
|
||||
#define EXEC_EXPR_H
|
||||
|
||||
#include "executor/nodeAgg.h"
|
||||
#include "nodes/execnodes.h"
|
||||
|
||||
/* forward references to avoid circularity */
|
||||
@ -64,9 +65,9 @@ typedef enum ExprEvalOp
|
||||
EEOP_WHOLEROW,
|
||||
|
||||
/*
|
||||
* Compute non-system Var value, assign it into ExprState's
|
||||
* resultslot. These are not used if a CheckVarSlotCompatibility() check
|
||||
* would be needed.
|
||||
* Compute non-system Var value, assign it into ExprState's resultslot.
|
||||
* These are not used if a CheckVarSlotCompatibility() check would be
|
||||
* needed.
|
||||
*/
|
||||
EEOP_ASSIGN_INNER_VAR,
|
||||
EEOP_ASSIGN_OUTER_VAR,
|
||||
@ -218,6 +219,17 @@ typedef enum ExprEvalOp
|
||||
EEOP_SUBPLAN,
|
||||
EEOP_ALTERNATIVE_SUBPLAN,
|
||||
|
||||
/* aggregation related nodes */
|
||||
EEOP_AGG_STRICT_DESERIALIZE,
|
||||
EEOP_AGG_DESERIALIZE,
|
||||
EEOP_AGG_STRICT_INPUT_CHECK,
|
||||
EEOP_AGG_INIT_TRANS,
|
||||
EEOP_AGG_STRICT_TRANS_CHECK,
|
||||
EEOP_AGG_PLAIN_TRANS_BYVAL,
|
||||
EEOP_AGG_PLAIN_TRANS,
|
||||
EEOP_AGG_ORDERED_TRANS_DATUM,
|
||||
EEOP_AGG_ORDERED_TRANS_TUPLE,
|
||||
|
||||
/* non-existent operation, used e.g. to check array lengths */
|
||||
EEOP_LAST
|
||||
} ExprEvalOp;
|
||||
@ -573,6 +585,55 @@ typedef struct ExprEvalStep
|
||||
/* out-of-line state, created by nodeSubplan.c */
|
||||
AlternativeSubPlanState *asstate;
|
||||
} alternative_subplan;
|
||||
|
||||
/* for EEOP_AGG_*DESERIALIZE */
|
||||
struct
|
||||
{
|
||||
AggState *aggstate;
|
||||
FunctionCallInfo fcinfo_data;
|
||||
int jumpnull;
|
||||
} agg_deserialize;
|
||||
|
||||
/* for EEOP_AGG_STRICT_INPUT_CHECK */
|
||||
struct
|
||||
{
|
||||
bool *nulls;
|
||||
int nargs;
|
||||
int jumpnull;
|
||||
} agg_strict_input_check;
|
||||
|
||||
/* for EEOP_AGG_INIT_TRANS */
|
||||
struct
|
||||
{
|
||||
AggState *aggstate;
|
||||
AggStatePerTrans pertrans;
|
||||
ExprContext *aggcontext;
|
||||
int setno;
|
||||
int transno;
|
||||
int setoff;
|
||||
int jumpnull;
|
||||
} agg_init_trans;
|
||||
|
||||
/* for EEOP_AGG_STRICT_TRANS_CHECK */
|
||||
struct
|
||||
{
|
||||
AggState *aggstate;
|
||||
int setno;
|
||||
int transno;
|
||||
int setoff;
|
||||
int jumpnull;
|
||||
} agg_strict_trans_check;
|
||||
|
||||
/* for EEOP_AGG_{PLAIN,ORDERED}_TRANS* */
|
||||
struct
|
||||
{
|
||||
AggState *aggstate;
|
||||
AggStatePerTrans pertrans;
|
||||
ExprContext *aggcontext;
|
||||
int setno;
|
||||
int transno;
|
||||
int setoff;
|
||||
} agg_trans;
|
||||
} d;
|
||||
} ExprEvalStep;
|
||||
|
||||
@ -669,4 +730,13 @@ extern void ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op,
|
||||
extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
|
||||
ExprContext *econtext);
|
||||
|
||||
extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup);
|
||||
extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
|
||||
Datum newValue, bool newValueIsNull,
|
||||
Datum oldValue, bool oldValueIsNull);
|
||||
extern void ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
|
||||
ExprContext *econtext);
|
||||
extern void ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
|
||||
ExprContext *econtext);
|
||||
|
||||
#endif /* EXEC_EXPR_H */
|
||||
|
Reference in New Issue
Block a user