Expression based aggregate transition / combine function invocation

Started by Andres Freundalmost 9 years ago3 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t37784
psql -h localhost -U postgres

Built from patchset v3 (message #3), August 18, 2026 at 04:59 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t37784_3 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t37784_3 && git checkout t37784_3

Patchset v3 (message #3) is on t37784_3

Jump to latest
#1Andres Freund
andres@anarazel.de

Hi,

this is part of my work to make expression evaluation JITable. In a lot
of analytics queries the major bottleneck is transition function
invocation (makes sense, hardly anyone wants to see billions of
rows). Therefore for JITing to be really valuable transition function
stuff needs to be JITable.

Excerpt from the preliminary commit message:

Previously aggregate transition and combination functions were invoked
by special case code in nodeAgg.c, evaluting 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
- 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.

While this gets rid of a substantial amount of duplication between the
infrastructure for transition and combine functions, it still increases
codesize a bit.

Todo / open Questions:
- Location of transition function building functions. Currently they're
in execExpr.c. That allows not to expose a bunch of functions local to
it, but requires exposing some aggregate structs to the world. We
could go the other way round as well.

- Right now we waste a bunch of time by having to access transition
states indexed by both grouping set number and the transition state
offset therein. It'd be nicer if we could cheaply reduce the number of
indirections, but I can't quite see how without adding additional
complications.

Here's some example tpch Q01 timings:
master: 11628 ms (best of three)
patches: 10330 ms (best of three)

other tpch queries are similar, aggregate improvement is a factor of
x 1.04.

Greetings,

Andres Freund

Attachments:

0001-Simplify-representation-of-aggregate-transition-valu.patchtext/x-diff; charset=us-asciiDownload+48-53
0002-More-efficient-AggState-pertrans-iteration.patchtext/x-diff; charset=us-asciiDownload+15-14
0003-Expression-evaluatation-based-agg-transition-invocat.patchtext/x-diff; charset=us-asciiDownload+1189-793
#2Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#1)
Re: Expression based aggregate transition / combine function invocation

Hi,

On 2017-11-27 16:31:21 -0800, Andres Freund wrote:

this is part of my work to make expression evaluation JITable. In a lot
of analytics queries the major bottleneck is transition function
invocation (makes sense, hardly anyone wants to see billions of
rows). Therefore for JITing to be really valuable transition function
stuff needs to be JITable.

Excerpt from the preliminary commit message:

Previously aggregate transition and combination functions were invoked
by special case code in nodeAgg.c, evaluting 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
- 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.

While this gets rid of a substantial amount of duplication between the
infrastructure for transition and combine functions, it still increases
codesize a bit.

There's still two callers of advance_transition_function() left, namely
process_ordered_aggregate_{single,multi}. Rearchitecting this so they
also go through expression-ified transition invocation seems like
material for a separate patch, this is complicated enough...

Todo / open Questions:
- Location of transition function building functions. Currently they're
in execExpr.c. That allows not to expose a bunch of functions local to
it, but requires exposing some aggregate structs to the world. We
could go the other way round as well.

I've left this as is.

- Right now we waste a bunch of time by having to access transition
states indexed by both grouping set number and the transition state
offset therein. It'd be nicer if we could cheaply reduce the number of
indirections, but I can't quite see how without adding additional
complications.

I've left this as is.

Here's a considerably polished variant of this patch. I plan to do
another round of polishing next week, and then push it, unless somebody
else has comments.

Regards,

Andres

#3Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#2)
Re: Expression based aggregate transition / combine function invocation

Here's a considerably polished variant of this patch.

And for realz.

Attachments:

t37784_3
0001-Expression-evaluatation-based-agg-transition-invocat.patchtext/x-diff; charset=us-asciiDownload+1235-798