Hibernate session.createCriteria and session.get performance

Our development team recently became concerned that benchmarks and HQL are too slow. I ran some tests to figure out where the slowness is coming from.

I have executed the following requests 1001 times. The first time a request is run, the object is not cached by the session, but each time the object is cached thereafter.

Entity e = (Entity) session.get(Entity.class, new EntityID("Composite key value 1", "Composite key value 2"));

First call: 
    80.505875
Average of next 1000 calls:
    0.045958 ms

Entity e = (Entity) session.createCriteria(Entity.class)
        .add(Restrictions.eq("id", new EntityID("Composite key value 1", "Composite key value 2")))
        .uniqueResult();

First call: 
    91.489098 ms
Average of next 1000 calls:
    0.847434 ms

      

As a side note, the same query in HQL took longer the first time, but was statistically equivalent for all subsequent calls.

I read that the criteria for translating HQL and HQL to SQL takes a negligible amount of time compared to database queries. According to my tests, these translations seem to take 18.4 times longer than a session.

0.847434 / 0.045958 = 18.439314

      

Assuming some implementation details, I expect to translate requests to take 0.801476ms. This means that the translation step takes 17.4 times until the session is received. With JDBC, we can run these queries in under 0.025368ms. This is a conversion project that used ODBC previously, so we are looking for speeds that are comparable to what we had before. However, even with caching, it seems that we cannot come close to comparable speeds.

(0.847434 - 0.045958) / 0.045958 = 17.439314

      

I expected that by using caching to avoid talking to the database, we would achieve speeds comparable to JDBC on subsequent calls. Is it okay to translate criteria to use most of a millisecond to run? How do people achieve speed comparable to JDBC with criteria-based caching?

Edit: There was a big error in my post where it looks like the same code created two different statistics. This has now been fixed.

+3


source to share


1 answer


I have executed the following requests 1001 times. The first time a query is run, the entity is not cached by the session, but each time thereafter, the session is cached.

Your guess is wrong. When using the criteria API, query criteria are not cached in the persistence context. Even though you are using the id property, the SQL query is being executed. Whereas when using the method, the get

object is actually maintained in the first level cache (persistence context).

You can check it by turning it on show_sql=true

. For the first use case, you will see a printout of one request. For the criteria, you will see 1000 requests.



The reason the first warm-up call is significantly slower is because the connection has to be pooled / created, the assertion can be cached, etc.

Speaking of which, by adding setCacheable(true)

to the criteria, you will see the average time approaching the challenge level get

.

0


source







All Articles