On 03/13/2017 06:30 PM, George Neuner wrote:
Hi Ryan,
On 3/13/2017 5:43 PM, Ryan Culpepper wrote:
Racket's db library always prepares a statement before executing it,
even if there are no query parameters. When allowed, instead of
closing the prepared statement immediately after executing it, the
connection stores it in a (Racket-side, per-connection) cache. The
cache key is just the SQL string. If you use the same query string
with different parameters, you'll still get the cached prepared
statement.
To extend my previous example:
> (query c "select $1::integer" 1)
....
** caching statement
....
> (query c "select $1::integer" 2)
** using cached statement
....
On the other hand, if the query string is not identical, it misses the
cache.
Hmm. Then what is the purpose of having separate (prepare ...)?
Explicit control, history (the statement cache is much newer), and
reflection (eg prepared-statement-result-types).
And what happens if the unknowing user issues a PREPARE statement for the
query directly to the DBMS?
You mean like PostgreSQL's PREPARE/EXECUTE commands? Those should work
fine too, as long as the statements are given names distinct from the
obscure names chosen by the db library.
Then there is the issue that deliberately prepared queries are not
optimized as heavily as normal queries - which is the case in pretty
much every DBMS that exists. Heavyweight queries that require maximum
performance are harmed by preparation.
In general, performing a query consists of three steps: Prepare, Bind,
and Execute. When there's a "one-step" approach, it's just a convenience
wrapper around those three steps. So I'd be very surprised if Prepare
intrinsically slowed down a query.
Maybe you mean that *parameterization* inhibits the query planner,
because query planning doesn't take the values of query parameters into
account. That seems to depend on the backend. PostgreSQL did planning at
Prepare time before version 9.2 and does it at Bind time since 9.2
("typically", the docs say). I don't know about other systems. But in
any case, parameterization is under the control of the user.
If that's not what you meant, can you elaborate?
Moreover, prepared queries are not cached in the normal sense ... they
persist until explicitly dropped, or until the connection is closed.
There are both per connection and global limits on the number of
prepared queries, and bad things can happen if these limits are
exceeded [e.g., I've seen versions of Postgresql freeze and Sybase
crash in such circumstances]. A long running application using pool
connections could get into trouble.
The statement cache is limited to 20 statements by default, and the
statement cache is only enabled within transactions and flushed on
commit/rollback. Also, connections returned to a connection pool with an
open transaction are disconnected rather than reused.
Ryan
--
You received this message because you are subscribed to the Google Groups "Racket
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.