-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Douglas E. Fajardo wrote:
> John Stanton has correctly pointed out that there is a programming model here 
> an application 
> effectively does the cacheing itself by precompiling statements at startup. 
> In this situation, 
> the proposed cacheing feature represents double work, and double memory (or 
> worse).

Precompiling statements is not caching.  There would not be double work
even if the application implements its own caching.

The way a cache would work is that the sqlite3 pointer would contain an
extra data structure to store cached statements.  There is already a
hash type that is appropriate and would consume about 28 bytes of memory
if empty.

When sqlite3_prepare is called, the cache is consulted.  If there is no
entry then the current prepare is run.  When sqlite3_finalize is called
then instead of freeing, the statement is put in the statement cache.

>  John Stanton has correctly pointed out that there is a programming model 
> here an application effectively does the cacheing itself by precompiling
statements at startup.

That is not caching and it would be unaffected by any caching scheme.
sqlite3_finalize would never be called so nothing would enter the cache.
 sqlite3_prepare would be called a few times but the queries would not
be in the cache.  This is no different than today.

> In this situation, the proposed cacheing feature represents double
work, and double memory (or worse).

There is never double work.  The point of a statement cache is to avoid
calling prepare!

If the application had a cache and SQLite had a cache then you still
wouldn't have the same statement in both caches since it would be on
eviction from the application cache that the SQLite cache would see a
statement.

There is one way to increase memory consumption, but only a bit.  That
is on prepare to add the statement to the cache immediately rather than
waiting till finalize.  If the same query is used again then you
duplicate the statement in the cache.

This can be mitigated by splitting the current sqlite3_stmt into two
pieces.  One piece is the byte code and other meta-data and the second
piece is the data that changes while the statement executes (registers
etc).  If a statement is only in use once then the extra memory
consumption would consist of a pointer between the two pieces.  If the
statement is used multiple times then you get a memory saving since the
static piece would only exist once rather than per statement as is the
case now.  You would also save on the copy of the query string each
sqlite3_prepare_v2 makes since you would only need it once.

>  My proposal of a statement cache, which Rodger Binns supports,

(*Roger* - no 'd') I don't necessarily support a SQLite statement cache,
but I do think it important the issue is discussed and whichever way
things go is documented in the ticket so that it doesn't have to be
discussed again :-)

I already have a statement cache in my code (265 lines of executable
code - no counting of comments, declarations etc).  It works well, is
threadsafe and re-entrant and handles multiple statements correctly.
Getting everything right is hard especially the corner cases.  (Just
because it runs doesn't make it right!)

If everyone is implementing their own statement cache then I strongly
support SQLite doing it instead since it will be way better and not
wasting every developer's time.

Looking at the costs:

* A hash table in sqlite3 * (about 28 bytes empty)

* (Option A) A lazy cache that puts finalized statements into cache

* (Option B) An eager cache that puts prepared statements into cache at
prepare time, but splits into static and dynamic parts

For a simple program that calls prepare at startup then the costs are
negligible.  Option A would never result in any entries (finalize not
called).  Option B would but each stmt would grow by a pointer and a
reference count over today's stmt.  If the same query is prepared
multiple times (eg if it was used in multiple threads) then Option A has
the same memory consumption and Option B *saves* memory.

Since caches could be compiled out, or run time switchable that would
satisfy everyone anyway.  If caches are as prevalent as seems to be the
case then that is a very strong argument for the code to be part of the
core.  As SQLite is being used in more and more places and wrapped for
more and more languages and environments then the cache makes even more
sense.

Roger
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkkYoQEACgkQmOOfHg372QT0jgCdEyXuvxrzbEZgtai+WwSlA2uT
T5EAnApwMA69jgOhuPerQ07utRD5iqX0
=Zuue
-----END PGP SIGNATURE-----
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to