现在,与JDBC的连接池是否仍在提高性能?

时间:2011-07-01 10:43:52

标签: java performance jdbc connection-pooling

我的应用程序没有使用任何形式的连接池,我直接使用连接。该应用程序主要执行简短的查询。从日志中我可以看到它经常打开和关闭连接,通常只在中间执行一行或几行的单个选择。这些通常需要约100毫秒(包括打开和关闭连接)。

关于连接池如何提高应用程序性能,有无数文章和博客条目,但它们似乎都相当陈旧(5年或更长时间)。

连接池是否仍然提供合理的性能优势或是否已过时。我正在使用SQLServer 2008和Microsofts JDBC驱动程序3.0版,如果这很重要的话。


结果/更新:自从我提出这个问题以来,发生了很多事情(我们切换了JDBC驱动程序和许多其他内容)。在某些时候,我做了很多重构和其他的东西,在那个机构也添加了连接池到该应用程序。 通过连接池,一些查询现在执行的速度比日志时间戳粒度可以测量的速度快(我相信不到16毫秒)。

总而言之,如果您需要经常连接/断开连接,那么连接池仍然是值得的。

2 个答案:

答案 0 :(得分:4)

这在某种程度上取决于数据库软件。一些(例如MySQL)具有相对轻量级的连接,可以快速打开。像Oracle这样的其他人有很多连接,这些连接都是严重的开销。

一般而言,最好使用连接池,尤其是来进行快速,简短,高容量的查询。您的应用包含连接的速度越快,重要性就越大。这种情况在过去几年中没有改变 - 如果有的话,它比以往任何时候都更重要,因为应用程序会扩大并变得更加复杂。

如果你需要说服力,我建议你做一些基准测试,有游泳池和不用。如果您在特定情况下没有获得性能优势,那么可能不值得打扰。

答案 1 :(得分:4)

如果每个查询100毫秒对您没问题,那么您不需要连接池。如果您需要小于20毫秒的查询,则重用连接至关重要。

如果您的驱动程序支持自己的连接池,我建议您使用它(如果它已经不适合您)。只有当你想要更好地控制如何汇集连接时,你才可以使用一个额外的库(我自己从来没有很好地使用它)

注意:您无需使用池来重用连接。

重用连接的一种简单方法是使用一个持久连接(具有适当的线程安全防护)如果您的查询很少,这可能就是您所需要的。

如果您希望能够同时执行查询并且只有几个线程可以执行查询,则可以在ThreadLocal字段中存储连接。

如果您想要多个连接,并且您有更多的线程可以执行查询而不是您想要的连接,请使用池。

对于ThreadLocal模型,您可以

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

如果要控制连接的清理方式。

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();
         }
     }
}

如果您担心获得死连接,可以在返回之前覆盖ThreadLocal的get()来测试连接。

相关问题