JDBC SQL 服务器的连接池:DBCP vs C3P0 vs 无池

JDBC Connection pooling for SQL Server: DBCP vs C3P0 vs No Pooling

我得到了这个 Java 网络应用程序,它恰好与 SQL 服务器数据库通信过多。我想决定如何有效地管理与该数据库的连接。想到的第一个选项是使用连接池第三方。我选择了 C3P0 和 DBCP 并准备了一些测试用例来比较这些方法,如下所示:

无池化:

public static void main(String[] args) {
        long startTime=System.currentTimeMillis();
        try {
            for (int i = 0; i < 100; i++) {
                Connection conn = ConnectionManager_SQL.getInstance().getConnection();

                String query = "SELECT * FROM MyTable;";
                PreparedStatement prest = conn.prepareStatement(query);

                ResultSet rs = prest.executeQuery();
                if (rs.next()) {
                    System.out.println(i + ": " + rs.getString("CorpName"));
                }
                conn.close();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs");
    }

DBCP:

public static void main(String[] args) {
        long startTime=System.currentTimeMillis();
        try {
            for (int i = 0; i < 100; i++) {
                Connection conn = ConnectionManager_SQL_DBCP.getInstance().getConnection();

                String query = "SELECT * FROM MyTable;";
                PreparedStatement prest = conn.prepareStatement(query);

                ResultSet rs = prest.executeQuery();
                if (rs.next()) {
                    System.out.println(i + ": " + rs.getString("CorpName"));
                }
                conn.close();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs");
    }

C3P0:

public static void main(String[] args) {
        long startTime=System.currentTimeMillis();
        try {
            for (int i = 0; i < 100; i++) {
                Connection conn = ConnectionManager_SQL_C3P0.getInstance().getConnection();

                String query = "SELECT * FROM MyTable;";
                PreparedStatement prest = conn.prepareStatement(query);

                ResultSet rs = prest.executeQuery();
                if (rs.next()) {
                    System.out.println(i + ": " + rs.getString("CorpName"));
                }
                conn.close();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs");
    }

结果如下:

Max Pool size for c3p0 and dbcp=10
c3p0: 5534 milli secs
dbcp: 4807 milli secs
No Pooling: 2660 milli secs

__

Max Pool size for c3p0 and dbcp=100
c3p0: 4937 milli secs
dbcp: 4798 milli secs
No Pooling: 2660 milli secs

有人可能会说池库的初始化和启动时间可能会影响这些测试用例的结果。我在循环中用更大的数字重复了它们,结果几乎相同。

令人惊讶的是,无池方法比连接池方法快得多。虽然我假设当我们在物理上关闭一个连接时,获得一个新连接肯定更耗时。

那么,这是怎么回事?

EDIT_01:c3p0 和 dbcp 配置

c3p0:

cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(100);
cpds.setMaxStatements(1000);

dbcp:

basicDataSource.setMinIdle(5);
basicDataSource.setMaxIdle(30);
basicDataSource.setMaxTotal(100);
basicDataSource.setMaxOpenPreparedStatements(180);

其余配置保持默认。值得一提的是,所有连接都是为本地主机上的数据库建立的。

c3p0 并不比门钉死。它很旧但(有点)积极维护。更新的替代品是否更适合您的应用程序由您决定。

您使用的是什么版本的 c3p0?如果您认为它比门钉还死,那么您使用的是旧版本吗?你应该使用 0.9.5.2.

您所定义的测试结果将在很大程度上取决于许多难以用您提供的信息进行评估的事情。正如 Mark Rotteveel 指出的那样,您没有显示任何关于您的配置的信息。您还没有提到 SQL 服务器的位置。当数据库位于远程时,您会注意到连接池比本地数据库有更大的好处,因为一些性能改进来自于在多个客户端使用中分摊连接获取的网络延迟。您的测试执行查询并遍历结果集。结果集越长,连接池(必须代理 ResultSet)的开销就越多,超过了更快获取连接的好处。 (不过,你得到的数字看起来异常糟糕。c3p0 通常具有非常快的 ResultSet 直通性能。)如果查询足够长,连接获取的成本可以忽略不计,如果遍历 ResultSet,池库的开销会增加,使连接池没那么有用。

但这与 Web 或移动客户端的典型用例相去甚远,后者通常会进行简短的查询、插入和更新。对于短查询、插入和更新,从头 连接获取的成本相对于查询的执行可能非常大。这是连接池提供很大改进的用例。那可能不是您要测试的;这取决于 MyTable 有多大。