From: | Marti Raudsepp <marti(at)juffo(dot)org> |
---|---|
To: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | [WIP] Caching constant stable expressions per execution |
Date: | 2011-09-10 22:27:17 |
Message-ID: | CABRT9RC-1wGxZC_Z5mwkdk70fgY2DRX3sLXzdP4voBKuKPZDow@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi,
This is a proof of concept patch for recognizing stable function calls
with constant arguments and only calling them once per execution. I'm
posting it to the list to gather feedback whether this is a dead end
or not.
Last time when this was brought up on the list, Tom Lane commented
that doing the checks for constant folding probably outweigh the
gains. http://archives.postgresql.org/pgsql-hackers/2010-11/msg01641.php
Yesterday I was looking at evaluate_function(), where currently
function constant folding happens, and realized that most of the
knowledge needed to implement this for FuncExpr and OpExpr (and
combinations thereof) is already there. This would probably cover 90%
of the use cases with very little overhead. Other expression types
can't be supported very well with this approach, notably case
expressions and AND/OR/NOT.
However, the code isn't very pretty. It works by changing
evaluate_function() to recognize stable/immutable functions with
constant stable/immutable arguments that aren't eligible for constant
folding. It sets a new boolean attribute FuncExpr.stableconst which is
checked during the function's first execution. If true, the result is
stored in ExprState and evalfunc is replaced with a new one that
returns the cached result.
Most common use cases cover timestamptz expressions (because they are
never immutable) such as:
ts>=to_timestamp('2010-01-01', 'YYYY-MM-DD')
ts>=(now() - interval '10 days')
Typically an index on the column would marginalize performance lost by
repeatedly evaluating the function.
----
Test data (1,051,777 rows, 38MB):
create table ts as select generate_series(timestamptz '2001-01-01',
'2011-01-01', '5min') ts;
Test query (using pgbench -T 30, taking the best of 3 runs):
select * from ts where ts>=to_timestamp('2001-01-01', 'YYYY-MM-DD')
and ts<=to_timestamp('2001-01-01', 'YYYY-MM-DD');
Unpatched tps = 0.927458
Patched tps = 6.729378
There's even a measurable improvement from caching now() calls:
select * from ts where ts>now();
Unpatched tps = 8.106439
Patched tps = 9.401684
Regards,
Marti
Attachment | Content-Type | Size |
---|---|---|
const-stable-expressions.patch | text/x-patch | 12.7 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Marti Raudsepp | 2011-09-10 22:43:50 | Re: [REVIEW] prepare plans of embedded sql on function start |
Previous Message | Tom Lane | 2011-09-10 22:21:22 | Re: [REVIEW] prepare plans of embedded sql on function start |