Thread: parametrized statements, but always replan?

parametrized statements, but always replan?

From
Kevin Murphy
Date:
Sorry for the newbie question here.  The documentation
(documentation/81/server-prepare.html) isn't clear about this point.
I'm using PG 8.1 with the matching jdbc driver.

Will the following code execute the query with a custom plan based on
the value of var (assuming no use of the prepare threshold)?

        prestmt = conn.prepareStatement(query);
        prestmt.setString(1, var);
        resultSet = prestmt.executeQuery();
        // ... use result set ...
        resultSet.close();
        prestmt.close();

I'd like the safety of parametrized SQL statements combined with the
greater performance (for certain queries) of having every statement
planned based on the specific parameters.  Ideally, I'd like to use
prepareStatement() and executeQuery() with out-of-band parameters, but
have the finished statement be custom-planned.  Most of my queries
wouldn't benefit from the "plan once, execute many times" model.

I've read documentation/81/server-prepare.html, but somehow it wasn't
clear.  It makes it sound as if by default, server-side prepared
statements are not really used ("There are a number of ways to enable
server side prepared statements ..."), which would be good for me.

But looking at my postgresql log, that doesn't seem to be the case; I
see PREPARE, BIND, and EXECUTE lines for each query.

Thanks,
Kevin Murphy


Re: parametrized statements, but always replan?

From
Dave Cramer
Date:
Kevin,

The only time prepared statements won't replan is if you re-use the
prepared statement, which your code does not.

However... AFAIK, postgresql does not plan based on the parameter.

Dave
On 20-Dec-06, at 2:44 PM, Kevin Murphy wrote:

> Sorry for the newbie question here.  The documentation
> (documentation/81/server-prepare.html) isn't clear about this
> point.  I'm using PG 8.1 with the matching jdbc driver.
>
> Will the following code execute the query with a custom plan based
> on the value of var (assuming no use of the prepare threshold)?
>
>        prestmt = conn.prepareStatement(query);
>        prestmt.setString(1, var);
>        resultSet = prestmt.executeQuery();
>        // ... use result set ...
>        resultSet.close();
>        prestmt.close();
>
> I'd like the safety of parametrized SQL statements combined with
> the greater performance (for certain queries) of having every
> statement planned based on the specific parameters.  Ideally, I'd
> like to use prepareStatement() and executeQuery() with out-of-band
> parameters, but have the finished statement be custom-planned.
> Most of my queries wouldn't benefit from the "plan once, execute
> many times" model.
>
> I've read documentation/81/server-prepare.html, but somehow it
> wasn't clear.  It makes it sound as if by default, server-side
> prepared statements are not really used ("There are a number of
> ways to enable server side prepared statements ..."), which would
> be good for me.
>
> But looking at my postgresql log, that doesn't seem to be the case;
> I see PREPARE, BIND, and EXECUTE lines for each query.
>
> Thanks,
> Kevin Murphy
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>       choose an index scan if your joining column's datatypes do not
>       match
>


Re: parametrized statements, but always replan?

From
Mark Lewis
Date:
Set the prepareThreshold to 0, meaning that it will never create a
"real" server-side prepared statement.

There will still be a protocol level PREPARE/BIND/EXECUTE passed to the
back-end because that's the way the V3 protocol works, but that's not
the same thing.  The planner will still see the actual query values.

-- Mark Lewis

On Wed, 2006-12-20 at 14:44 -0500, Kevin Murphy wrote:
> Sorry for the newbie question here.  The documentation
> (documentation/81/server-prepare.html) isn't clear about this point.
> I'm using PG 8.1 with the matching jdbc driver.
>
> Will the following code execute the query with a custom plan based on
> the value of var (assuming no use of the prepare threshold)?
>
>         prestmt = conn.prepareStatement(query);
>         prestmt.setString(1, var);
>         resultSet = prestmt.executeQuery();
>         // ... use result set ...
>         resultSet.close();
>         prestmt.close();
>
> I'd like the safety of parametrized SQL statements combined with the
> greater performance (for certain queries) of having every statement
> planned based on the specific parameters.  Ideally, I'd like to use
> prepareStatement() and executeQuery() with out-of-band parameters, but
> have the finished statement be custom-planned.  Most of my queries
> wouldn't benefit from the "plan once, execute many times" model.
>
> I've read documentation/81/server-prepare.html, but somehow it wasn't
> clear.  It makes it sound as if by default, server-side prepared
> statements are not really used ("There are a number of ways to enable
> server side prepared statements ..."), which would be good for me.
>
> But looking at my postgresql log, that doesn't seem to be the case; I
> see PREPARE, BIND, and EXECUTE lines for each query.
>
> Thanks,
> Kevin Murphy
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match

Re: parametrized statements, but always replan?

From
Kevin Murphy
Date:
Dave Cramer wrote:
> The only time prepared statements won't replan is if you re-use the
> prepared statement, which your code does not.
>
> However... AFAIK, postgresql does not plan based on the parameter.

OK, PG definitely plans based on the parameter value.   I turned on plan
logging in the server log, and without specifying prepareThreshold at
all (e.g. setting it to 0), I can see that PG is making different plan
estimates for different parameter values.  It might be using the same
general plan, but I can't bear to wade through all that output to tell.
Looking at ANALYZE output on the unadorned, non-prepared query, I can
see that different plans may be made, depending on the parameter.  In a
table with millions of rows, there are tens of thousands of distinct
values of this parameter, with a very wide distribution.  One value has
200K occurrences, many others just a handful.  Using a different plan
for the outliers can be (and is) very helpful.  When I wrap the query in
a SQL PREPARE statement, a generic plan is made that works OK for 99.9%
of the column values, but for the most common column value, that plan is
20,000 times slower than the plan that is chosen by the planner when it
knows that the query involves that most common value.  Hence my interest
in what is going on behind prepareStatement().  I'm good now.

-Kevin Murphy


Re: parametrized statements, but always replan?

From
Kevin Murphy
Date:
Mark Lewis wrote:
> Set the prepareThreshold to 0, meaning that it will never create a
> "real" server-side prepared statement.
Hmm, even by default (without specifying prepareThreshold), it seems
that the planner looks at the parameter values for the first execution
of the query.  (See my post a couple minutes ago*).  Am I mistaken?

If I'm not mistaken, then for one-shot queries, is there any any
additional advantage to setting prepareThreshold to 0?

BTW, is the default value of prepareThreshold is 1?

Thanks,
Kevin Murphy

* From my post a couple of minutes ago:
> OK, PG definitely plans based on the parameter value.   I turned on
> plan logging in the server log, and without specifying
> prepareThreshold at all (e.g. setting it to 0), I can see that PG is
> making different plan [cost] estimates for different parameter values.


Re: parametrized statements, but always replan?

From
Mark Lewis
Date:
On Wed, 2006-12-20 at 16:28 -0500, Kevin Murphy wrote:
> Mark Lewis wrote:
> > Set the prepareThreshold to 0, meaning that it will never create a
> > "real" server-side prepared statement.
> Hmm, even by default (without specifying prepareThreshold), it seems
> that the planner looks at the parameter values for the first execution
> of the query.  (See my post a couple minutes ago*).  Am I mistaken?
>
> If I'm not mistaken, then for one-shot queries, is there any any
> additional advantage to setting prepareThreshold to 0?

With the current driver version, there is no advantage if you only use
the PreparedStatement once.

> BTW, is the default value of prepareThreshold is 1?

The default value in the driver version I've got handy (forget exactly
which version this is) is 5.  I don't think that's changed recently.

-- Mark Lewis

Re: parametrized statements, but always replan?

From
Tom Lane
Date:
Dave Cramer <pg@fastcrypt.com> writes:
> The only time prepared statements won't replan is if you re-use the
> prepared statement, which your code does not.
> However... AFAIK, postgresql does not plan based on the parameter.

This was changed in 8.2: for an unnamed statement the planning step is
delayed until Bind time, so that the actual parameter values can be
considered.

            regards, tom lane