Prepared statements, parameters and logging

Lists: pgsql-jdbc
From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Prepared statements, parameters and logging
Date: 2007-06-25 10:47:29
Message-ID: 1182768449.13328.60.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Hi all,

I have a system (postgres 8.1) which was until now running with JDBC
parameter prepareThreshold=1 so it is always using server side prepares
(we had some trouble in the past if not setting it so). Now we are
prepared to set this to 0, meaning no server side prepares by default...

The problem is that I did the switch and I still see queries which are
presumably server side prepared (marked with <unnamed> in the log - I
enabled reporting queries longer than 2 seconds)...

The question is how do I tell for sure from the DB log if a query is
server side prepared or not ? I was presuming that <unnamed> in the log
means server side prepare, some name like 'C_xyz' means client side
prepared statement. Is this correct ?

Thanks,
Csaba.


From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 10:54:04
Message-ID: 6A182763-97EC-43C9-BD13-EE5375A83AC2@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Csaba,

They will all be prepared. The threshold is whether to re-use the
prepared statement.

What you are seeing is the use of unnamed statements.

If you really want them turned off use protocolVersion=2

Dave
On 25-Jun-07, at 6:47 AM, Csaba Nagy wrote:

> Hi all,
>
> I have a system (postgres 8.1) which was until now running with JDBC
> parameter prepareThreshold=1 so it is always using server side
> prepares
> (we had some trouble in the past if not setting it so). Now we are
> prepared to set this to 0, meaning no server side prepares by
> default...
>
> The problem is that I did the switch and I still see queries which are
> presumably server side prepared (marked with <unnamed> in the log - I
> enabled reporting queries longer than 2 seconds)...
>
> The question is how do I tell for sure from the DB log if a query is
> server side prepared or not ? I was presuming that <unnamed> in the
> log
> means server side prepare, some name like 'C_xyz' means client side
> prepared statement. Is this correct ?
>
> Thanks,
> Csaba.
>
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 3: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faq


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Dave Cramer <pg(at)fastcrypt(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 11:13:39
Message-ID: 1182770018.13328.63.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Actually what I'm interested in is to give the server the parameter
values for planning or not... before I wanted generic queries so I
didn't want the server to see the parameters, and now I want the server
to see them before creating the execution plan... am I turning the right
knob for this ?

Thanks,
Csaba.

On Mon, 2007-06-25 at 12:54, Dave Cramer wrote:
> Csaba,
>
> They will all be prepared. The threshold is whether to re-use the
> prepared statement.
>
> What you are seeing is the use of unnamed statements.
>
> If you really want them turned off use protocolVersion=2
>
> Dave
> On 25-Jun-07, at 6:47 AM, Csaba Nagy wrote:
>
> > Hi all,
> >
> > I have a system (postgres 8.1) which was until now running with JDBC
> > parameter prepareThreshold=1 so it is always using server side
> > prepares
> > (we had some trouble in the past if not setting it so). Now we are
> > prepared to set this to 0, meaning no server side prepares by
> > default...
> >
> > The problem is that I did the switch and I still see queries which are
> > presumably server side prepared (marked with <unnamed> in the log - I
> > enabled reporting queries longer than 2 seconds)...
> >
> > The question is how do I tell for sure from the DB log if a query is
> > server side prepared or not ? I was presuming that <unnamed> in the
> > log
> > means server side prepare, some name like 'C_xyz' means client side
> > prepared statement. Is this correct ?
> >
> > Thanks,
> > Csaba.
> >
> >
> >
> > ---------------------------(end of
> > broadcast)---------------------------
> > TIP 3: Have you checked our extensive FAQ?
> >
> > http://www.postgresql.org/docs/faq
>


From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 11:24:15
Message-ID: C8485EE8-2EA6-4C87-91CB-E5370A3BDC53@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

As far as I know you can't have both. In version 3 protocol,
everything is a server side prepared statement without parameters.

Dave
On 25-Jun-07, at 7:13 AM, Csaba Nagy wrote:

> Actually what I'm interested in is to give the server the parameter
> values for planning or not... before I wanted generic queries so I
> didn't want the server to see the parameters, and now I want the
> server
> to see them before creating the execution plan... am I turning the
> right
> knob for this ?
>
> Thanks,
> Csaba.
>
> On Mon, 2007-06-25 at 12:54, Dave Cramer wrote:
>> Csaba,
>>
>> They will all be prepared. The threshold is whether to re-use the
>> prepared statement.
>>
>> What you are seeing is the use of unnamed statements.
>>
>> If you really want them turned off use protocolVersion=2
>>
>> Dave
>> On 25-Jun-07, at 6:47 AM, Csaba Nagy wrote:
>>
>>> Hi all,
>>>
>>> I have a system (postgres 8.1) which was until now running with JDBC
>>> parameter prepareThreshold=1 so it is always using server side
>>> prepares
>>> (we had some trouble in the past if not setting it so). Now we are
>>> prepared to set this to 0, meaning no server side prepares by
>>> default...
>>>
>>> The problem is that I did the switch and I still see queries
>>> which are
>>> presumably server side prepared (marked with <unnamed> in the log
>>> - I
>>> enabled reporting queries longer than 2 seconds)...
>>>
>>> The question is how do I tell for sure from the DB log if a query is
>>> server side prepared or not ? I was presuming that <unnamed> in the
>>> log
>>> means server side prepare, some name like 'C_xyz' means client side
>>> prepared statement. Is this correct ?
>>>
>>> Thanks,
>>> Csaba.
>>>
>>>
>>>
>>> ---------------------------(end of
>>> broadcast)---------------------------
>>> TIP 3: Have you checked our extensive FAQ?
>>>
>>> http://www.postgresql.org/docs/faq
>>
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Dave Cramer <pg(at)fastcrypt(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 12:42:28
Message-ID: 1182775348.13328.69.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Dave,

If I read [1] correctly, the prepareThreshold parameter should actually
do what I want in protocol version 3... or am I misreading something ?

[1] http://jdbc.postgresql.org/documentation/81/server-prepare.html

Cheers,
Csaba.

On Mon, 2007-06-25 at 13:24, Dave Cramer wrote:
> As far as I know you can't have both. In version 3 protocol,
> everything is a server side prepared statement without parameters.


From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 13:11:39
Message-ID: 9537AA08-53BB-434E-9E62-F326AADED792@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

I think the text should be specifying that once you exceed
preparedThreshold executions the driver uses a named prepared
statement, and can re-use it. Otherwise it uses unnamed prepared
statements which need to be prepared for each execution.

Dave
On 25-Jun-07, at 8:42 AM, Csaba Nagy wrote:

> Dave,
>
> If I read [1] correctly, the prepareThreshold parameter should
> actually
> do what I want in protocol version 3... or am I misreading something ?
>
> [1] http://jdbc.postgresql.org/documentation/81/server-prepare.html
>
> Cheers,
> Csaba.
>
> On Mon, 2007-06-25 at 13:24, Dave Cramer wrote:
>> As far as I know you can't have both. In version 3 protocol,
>> everything is a server side prepared statement without parameters.
>
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Dave Cramer <pg(at)fastcrypt(dot)com>
Cc: Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 13:34:35
Message-ID: 1182778475.13328.79.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Mon, 2007-06-25 at 15:11, Dave Cramer wrote:
> I think the text should be specifying that once you exceed
> preparedThreshold executions the driver uses a named prepared
> statement, and can re-use it. Otherwise it uses unnamed prepared
> statements which need to be prepared for each execution.

OK, but I also thought that the value 0 means no reuse at all, i.e. it
should always prepare for each execution... and 1 should mean always
reuse, from the first statement on.

Before I was using prepareThreshold='1', and I was seeing only such
entries in the server log:

duration: 5437.499 ms statement: EXECUTE <unnamed> [PREPARE: SELECT
... ]

Note the <unnamed> in the log entry, it was always there for each
statement.

After setting prepareThreshold='0', I started getting 2 kinds of log
entries, the ones like above, and the likes:

duration: 2200.570 ms statement: EXECUTE C_220047 [PREPARE: SELECT
... ]

Note the C_220047, that's what's changed...

I distinctly remember discussing this issue some time ago on this list,
back then I needed the opposite action, to disable the one-time-prepare
by default... now I just need the opposite, to enable it by default even
for repetitive queries... is that possible ?

Cheers,
Csaba.


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Dave Cramer <pg(at)fastcrypt(dot)com>, Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 21:40:52
Message-ID: 46803664.3060701@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Csaba Nagy wrote:

> Before I was using prepareThreshold='1', and I was seeing only such
> entries in the server log:
>
> duration: 5437.499 ms statement: EXECUTE <unnamed> [PREPARE: SELECT
> ... ]
>
> Note the <unnamed> in the log entry, it was always there for each
> statement.

I believe that's logging execution of an unnamed portal, not an unnamed
statement. I'm not sure whether the current server logging actually lets
you tell whether a named statement was used/reused or not (at least that
was one of my complaints about early versions of it -- haven't checked
what current versions do).

If the statement name is logged, it'd be something like "S_12345".

> After setting prepareThreshold='0', I started getting 2 kinds of log
> entries, the ones like above, and the likes:
>
> duration: 2200.570 ms statement: EXECUTE C_220047 [PREPARE: SELECT
> ... ]
>
> Note the C_220047, that's what's changed...

C_.... are portals ("cursors")

If you're using setFetchSize() to avoid pulling in the whole resultset
at once, the driver has to use a named statement and named portal
regardless of the prepare-threshold setting (because portals are closed
when their creating statement is closed, and the unnamed statement gets
closed when reused)

-O


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Dave Cramer <pg(at)fastcrypt(dot)com>, Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-25 22:07:44
Message-ID: 46803CB0.2000009@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Csaba Nagy wrote:

(before:)

> duration: 5437.499 ms statement: EXECUTE <unnamed> [PREPARE: SELECT
> ... ]

(after:)

> duration: 2200.570 ms statement: EXECUTE C_220047 [PREPARE: SELECT
> ... ]

Also.. as to why you see the behaviour change, I'd guess that you're
using log_min_duration and the plans for the queries where you are using
setFetchSize() have changed from one with low startup cost to one with
high startup cost due to switching from named to unnamed statements. The
high startup cost plan means the very first portal execution takes
longer and gets logged.. the low startup cost plan might be more
expensive overall but the cost is spread out across all the portal
executions, so no one execution takes long enough to get logged.

-O


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Oliver Jowett <oliver(at)opencloud(dot)com>
Cc: Dave Cramer <pg(at)fastcrypt(dot)com>, Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-26 08:22:25
Message-ID: 1182846145.13328.95.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Mon, 2007-06-25 at 23:40, Oliver Jowett wrote:
> I believe that's logging execution of an unnamed portal, not an unnamed
> statement. I'm not sure whether the current server logging actually lets
> you tell whether a named statement was used/reused or not (at least that
> was one of my complaints about early versions of it -- haven't checked
> what current versions do).
>
> If the statement name is logged, it'd be something like "S_12345".

Thanks Oliver for your answer.

My real question is: am I turning the right knob with
"prepareThreshold=0" ? I want all queries to be planned taking into
account the parameter values by default. I can turn this off on special
cases by setting the prepare threashold on the statement level - if the
prepareThreshold is affecting at all the fact that parameters are sent
for planning or not... is it ?

I was supposing it is, but I could not figure it out from the logging -
and the results in query execution time seem to contradict what I get by
explain on a PREPARE (which suck the same as my production system) vs.
on direct sql with parameters included (which seems to yield the correct
plan). The actual case is a query including a table which has one id
value which has very skewed cardinality compared to the average, and the
generic plan sucks badly for this one id.

Thanks,
Csaba.


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Dave Cramer <pg(at)fastcrypt(dot)com>, Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-26 09:10:58
Message-ID: 4680D822.20205@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Csaba Nagy wrote:

> My real question is: am I turning the right knob with
> "prepareThreshold=0" ? I want all queries to be planned taking into
> account the parameter values by default. I can turn this off on special
> cases by setting the prepare threashold on the statement level - if the
> prepareThreshold is affecting at all the fact that parameters are sent
> for planning or not... is it ?

Short answer: yes, prepareThreshold=0 is the right knob. (with one
exception, see below)

Long answer:

The parameters are always sent out-of-line from the query when using
protocol version 3.

When the driver decides to use a "server prepared statement" (i.e. when
prepareThreshold > 0 and you've reused the same PreparedStatement
enough) it parses the query into a named statement at the protocol
level. Otherwise, it parses it into the unnamed statement.

When a named statement is parsed, the server also generates a generic
plan immediately.

When an unnamed statement is parsed, the parse phase is done but query
planning is not done. Later, when actual parameter values are bound,
planning is done using those actual parameter values for selectivity
purposes.

So the issue is not so much "how are the parameters sent?" but "is a
named statement being used or not?"

If you set prepareThreshold=0 then an unnamed statement should always be
used (& therefore actual parameter values should be taken into account
when planning), with one exception: the setFetchSize() case I described
in my earlier email. In that case the driver simply can't use the
unnamed statement because it needs the statement and portal to survive
for longer than using the unnamed statement would allow. Ideally the
protocol would let clients specify when to defer planning on a
per-statement basis, but the current situation is a result of wanting to
avoid exactly that sort of protocol change.. it's a bit of a compromise.

If you set logLevel=2 on the driver, you should be able to see the
differences in the protocol flow in more detail than the server logging
lets you see.

-O


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Oliver Jowett <oliver(at)opencloud(dot)com>
Cc: Dave Cramer <pg(at)fastcrypt(dot)com>, Postgres JDBC <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: Prepared statements, parameters and logging
Date: 2007-06-26 09:25:32
Message-ID: 1182849932.13328.107.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Oliver,

Now this was enlightening... now I finally understand the behavior I
see.

> If you set prepareThreshold=0 then an unnamed statement should always be
> used (& therefore actual parameter values should be taken into account
> when planning), with one exception: the setFetchSize() case I described
> in my earlier email.

The setFetchSize must be the cause I see the unnamed statements (I have
it automatically added to all of our select statements). For a query
with limit on it (the case of my problem-query), the fetch size is not
very useful, I'll get rid of it...

> If you set logLevel=2 on the driver, you should be able to see the
> differences in the protocol flow in more detail than the server logging
> lets you see.

Thanks for the tip, I'll do that too next time... for the current
situation your explanation is more then enough.

Thanks,
Csaba.