Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is connection pooling with JDBC still improving performance nowadays?

My application is not using any form of connection pooling, I'm working directly with connections. The application does mainly short, simple queries. From the log I can see that it frequently opens and closes connections, often performing only a single select of one or a few rows in between. These take typically ~100ms (including opening and closing the connection).

There are countless articles and blog entries on how connection pooling improves application performance, but they all seem to be rather old (5 or more years).

Does connection pooling still provide a reasonable performance benefit or had it become obsolete. I'm using SQLServer 2008 with Microsofts JDBC driver version 3.0, if that matters.


Results/Update: Many things happened since I have asked this question (we switches JDBC driver and lots of other stuff). At some time I did lots of refactorings and other stuff and at that apportunity also added connection pooling to that application. With connections pooling some queries execute now faster than the log timestamp granularity can measure (less than 16ms I believe).

So in conclusion, yes connection pooling is still worth the effort if you need to connect/disconnect frequently.

like image 842
Durandal Avatar asked Feb 24 '23 17:02

Durandal


1 Answers

If 100 ms per query is fine for you, then you don't need a connection pool. If you need queries which are less than 20 ms, reusing connections is essential.

If your driver supports its own connection pool, I suggest you use that (in case it doesn't do this for you already). Only if you want greater control over how connections are pooled you can use an additional library (never found a good use for one myself)

Note: you need not use a pool to re-use connections.

One simple way to reuse connections is to have one persistent connection (which has appropriate thread safety guards in place) If your queries are infrequent, this may be all you need.

If you want to be able perform queries concurrently and only have a few threads which will perform queries, you can store a connection in a ThreadLocal field.

If you want multiple connections and you have more threads which could perform a query than you want to have in connections, use a pool.

For the ThreadLocal model you can do

public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() {
     public Connection initialValue() {
         LOG.info(Thread.currentThread()+": created a connection.");
         return createConnection();
     }
};

If you want to control how the connections are cleaned up.

private static final Map<Thread, Connection> connections = new ConcurrentHashMap();
public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() {
     public Connection initialValue() {
         LOG.info(Thread.currentThread()+": created a connection.");
         Connection conn = createConnection();
         connections.put(Thread.currentThread(), conn);
         return conn;
     }
};
public static void cleanUp() {
     for(Map.Entry<Thread, Connection> entry: connections.entrySet()) {
         Thread t = entry.getKey();
         if (!t.isAlive()) {
             LOG.info(t+": closed a connection.");
             connections.remove(t);
             entry.getValue().close();
         }
     }
}

If you are concerned about getting a dead connection, you can override the get() of ThreadLocal to test the connection before returning.

like image 133
Peter Lawrey Avatar answered Mar 05 '23 15:03

Peter Lawrey