Spring DAO: la primera consulta con JdbcTemplate lleva mucho más tiempo

In my application I use Spring MVC with DAO pattern to access MSSql database with JdbcTemplate. Everything is working fine but I have noticed that first query takes a bit longer then next queries in each single request.

Escribí una prueba simple:

String sql = "SELECT 1";
for (int i = 0; i < 5; i++) {
    long startTime = System.currentTimeMillis();
    jdbcTemplate.queryForList(sql);
    logger.debug("query took: " + TimeHelper.showDuration(startTime));
}

el resultado es:

2012-08-28 12:55:07,665 | Start
2012-08-28 12:55:08,878 | query took: 424 milliseconds
2012-08-28 12:55:08,893 | query took: 15 milliseconds
2012-08-28 12:55:08,908 | query took: 14 milliseconds
2012-08-28 12:55:08,922 | query took: 14 milliseconds
2012-08-28 12:55:08,937 | query took: 14 milliseconds

I understand that there are some activities that Spring is doing to get all beans ready. But if there is request to server that executes only 1 query then it takes 424 miliseconds on each request.

My question is: Is this behavior OK? Or there can be some bug in my code? Does it work so that on each request Spring needs this time for initialization? (and all other queries in request will run fast then)? Or I can do some startup initialization and then during each request the first query will take 15 ms too?

My configuration is folowing:

datasource: class="org.apache.commons.dbcp.BasicDataSource"

dao is injected to test class with:

@Resource(name="testDao")  
private TestDao testDao;  

I use annotations based approach. Test class and DAO doesn't use @Transaction.

EDIT: I also tried to configure initialSize but this didn't help, (with initialSize=2 it takes 800ms, with initialSize=1 it takes 400ms - each request).

I don't understand why it takes 400ms on each request when it is possible to have it for 15 ms. It seems like some overhead with Spring. :(

preguntado el 28 de agosto de 12 a las 12:08

3 Respuestas

Your DataSource is a connection pool. The first query needs to connect. Subsequent queries reuse the connection. You could either configure dbcp to pre-create a few connections or connect and release manually right after the app starts.

Respondido 28 ago 12, 12:08

I tried to configure DBCP with initialSize = 2 (higher this number is the longer it takes), but this behaviour repeats on each reguest, so if I connect on start-up it will not help, it seems like all connection are closed when request is finished, or is there some problem with AOP (spring searching for some bean when calling jdbcTemplate.queryForList)? - user1335851

JDBC timings I measured a number of years back: establishing tcp connection ~700ms; preparing statement ~70ms; executing the statement ~10ms. So this really does sound like a timing for establishing a connection. I would look at connection pool configuration. Look at v$session to see how and when the jdbc connections are being established. If changing from 1 connection to 2 connections changes the time from 400ms to 800ms, that is another strong pointer this way. - Glenn

Echa un vistazo a la javadoc y fuente. getExceptionTranslator() probably involves some work to set up. Maybe you can control when that work happens with the lazy-init parámetro.

Respondido 28 ago 12, 13:08

I checked that connection pool and its connections (initialSize) are created during first call when connection is needed, and then later it is reused in all requests, this is how it should work :), I have also noticed that 400ms time is lower (about 100ms) when there are multiple requests at the same time. I think the reason for initial longer time is because of establishing a TCP connection as John Watts mentioned or because of some Spring background management.

Respondido 28 ago 12, 15:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.