Let's see if I can send this properly now to the list.
----- Forwarded Message -----
From: "Galder Zamarreno" <gzamarre(a)redhat.com>
To: "Steve Ebersole" <sebersol(a)redhat.com>
Cc: "Brian Stansberry" <bstansbe(a)redhat.com>,
hibernate-dev(a)lists.jboss.org
Sent: Monday, January 18, 2010 1:52:54 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome /
Stockholm / Vienna
Subject: Re: Query cache inefficiencies over longer Sessions
Had the wrong hibernate-dev list email on CC. Fixing it now.
----- Original Message -----
From: "Galder Zamarreno" <gzamarre(a)redhat.com>
To: "Steve Ebersole" <sebersol(a)redhat.com>
Cc: "Brian Stansberry" <bstansbe(a)redhat.com>, hibernate-dev(a)jboss.org
Sent: Monday, January 18, 2010 1:51:29 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome /
Stockholm / Vienna
Subject: Query cache inefficiencies over longer Sessions
Hi Steve,
I'm looking into a post by Guenther (
http://community.jboss.org/message/519752#519752)
where he explains issues he's encountering with query cache. He's already entered
two JIRAs before related to this:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-4551
http://opensource.atlassian.com/projects/hibernate/browse/HHH-4577
He had initially complained about the lack of precision of nextTimestamp in JBC/Infinispan
cache providers, but this precision deficiency is justified in a clustered environment, so
we're not planning to change it for the time being. Looking at his last comment, it
seems to me that his real problem is the fact that the timestamp query cache uses to store
the queries, or to check whether a query is up to date comes from timestamp of when the
session is created. The longer the sessions are, the least advantageous it is to use query
cache in the current form.
Now, my question is, why not use Region.nextTimestamp() as timestamp when queries are to
be cached rather than when the session was opened? This would most probably solve problems
like the ones this user has because by the time a query and its resulset had been
calculated, more than 100ms would have passed, assuming you don't use an in-memory
database, which is what's recommended anyway.
Also, why not use Region.nextTimestamp() as timestamp when a query is actually executed
when comparing with update timestamps rather than when session was opened?
I'm not an authority on Hibernate code, but I suspect the reason why the decision was
taken to use the timestamp when session is created might be because due to potential
isolation problems between concurrent sessions updating query/entity caches on
non-transactional cache providers. By using the timestamp when session was opened, you
guarantee that queries will be invalid from the moment that you started that session,
hence any partial updates that might have happened to caches between session open and
query execution won't be used by other sessions.
I don't think this would be a problem with transactional cache providers though, i.e.
infinispan/jbc. The fact that updates happen on commit time and transaction isolation
would protect from such situations.
I think it might be worth adding some configuration option that allows for more precision
for query caches used with transactional cache providers. Such option could force
Region.nextTimestamp() to be used to mark when queries are executed, and when these are
updated, rather when session was opened.
Thoughts?
Galder