Thread: spurious function execution in prepared statements.

spurious function execution in prepared statements.

From
"Merlin Moncure"
Date:
OK, I have a situation that might be a performance problem, a bug, or an
unavoidable consequence of using prepared statements.  The short version
is that I am getting function executions for rows not returned in a
result set when they are in a prepared statement.

In other words, I have a query:
select f(t.c) from t where [boolean expr on t] limit 1;

because of the limit phrase, obviously, at most one record is returned
and f executes at most once regardless of the plan used (in practice,
sometimes index, sometimes seq_scan.

Now, if the same query is executed as a prepared statement,
prepare ps(...) as select f(t.c) from t where [expr] limit 1;
execute ps;

now, if ps ends up using a index scan on t, everything is ok.  However,
if ps does a seqscan, f executes for every row on t examined until the
[expr] criteria is met.  Is this a bug?  If necessary I should be able
to set up a reproducible example.  The easy workaround is to not use
prepared statements in these situations, but I need to be able to
guarantee that f only executes once (even if that means exploring
subqueries).

Merlin

Re: spurious function execution in prepared statements.

From
Michael Adler
Date:
On Thu, Sep 30, 2004 at 09:45:51AM -0400, Merlin Moncure wrote:
> Now, if the same query is executed as a prepared statement,
> prepare ps(...) as select f(t.c) from t where [expr] limit 1;
> execute ps;
>
> now, if ps ends up using a index scan on t, everything is ok.  However,
> if ps does a seqscan, f executes for every row on t examined until the
> [expr] criteria is met.  Is this a bug?  If necessary I should be able
> to set up a reproducible example.  The easy workaround is to not use
> prepared statements in these situations, but I need to be able to
> guarantee that f only executes once (even if that means exploring
> subqueries).


Here's another workaround that may let you use a prepared statement:

prepare ps(...) as
select f(c) from (select c from t where [expr] limit 1) as t1

-Mike

Re: spurious function execution in prepared statements.

From
"Merlin Moncure"
Date:
> Here's another workaround that may let you use a prepared statement:
>
> prepare ps(...) as
> select f(c) from (select c from t where [expr] limit 1) as t1
>
> -Mike

I was just exploring that.  In fact, the problem is not limited to
prepared statements...it's just that they are more likely to run a
seqscan so I noticed it there first.  Since I am in a situation where I
need very strict control over when and why f gets executed, I pretty
much have to go with the subquery option.

That said, it just seems that out of result set excecutions of f should
be in violation of something...

Merlin


Re: [PERFORM] spurious function execution in prepared statements.

From
Stephan Szabo
Date:
On Thu, 30 Sep 2004, Merlin Moncure wrote:

> OK, I have a situation that might be a performance problem, a bug, or an
> unavoidable consequence of using prepared statements.  The short version
> is that I am getting function executions for rows not returned in a
> result set when they are in a prepared statement.
>
> In other words, I have a query:
> select f(t.c) from t where [boolean expr on t] limit 1;

An actual boolean expr on t? Or on a column in t?

> because of the limit phrase, obviously, at most one record is returned
> and f executes at most once regardless of the plan used (in practice,
> sometimes index, sometimes seq_scan.
>
> Now, if the same query is executed as a prepared statement,
> prepare ps(...) as select f(t.c) from t where [expr] limit 1;
> execute ps;
>
> now, if ps ends up using a index scan on t, everything is ok.  However,
> if ps does a seqscan, f executes for every row on t examined until the
> [expr] criteria is met.  Is this a bug?  If necessary I should be able
> to set up a reproducible example.  The easy workaround is to not use
> prepared statements in these situations, but I need to be able to
> guarantee that f only executes once (even if that means exploring
> subqueries).

I think a reproducible example would be good. Simple attempts to duplicate
this on 8.0b2 have failed for me, unless I'm using order by.

Re: spurious function execution in prepared statements.

From
Tom Lane
Date:
"Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> now, if ps ends up using a index scan on t, everything is ok.  However,
> if ps does a seqscan, f executes for every row on t examined until the
> [expr] criteria is met.  Is this a bug?

Works for me.

regression=# create function f(int) returns int as '
regression'# begin
regression'#   raise notice ''f(%)'', $1;
regression'#   return $1;
regression'# end' language plpgsql;
CREATE FUNCTION
regression=# select f(unique2) from tenk1 where unique2%2 = 1 limit 2;
NOTICE:  f(1)
NOTICE:  f(3)
 f
---
 1
 3
(2 rows)

regression=# prepare ps as
regression-# select f(unique2) from tenk1 where unique2%2 = 1 limit 2;
PREPARE
regression=# execute ps;
NOTICE:  f(1)
NOTICE:  f(3)
 f
---
 1
 3
(2 rows)

regression=#

You sure you aren't using f() in the WHERE clause?

            regards, tom lane