SQL Server 的 JDBC 连接池:DBCP、C3P0 与无池

SJ.*_*ari 0 sql-server connection-pooling jdbc c3p0 apache-commons-dbcp

我得到了这个 Java Web 应用程序,它恰好与 SQL Server 数据库进行了过多的通信。我想决定如何以有效的方式管理与该数据库的连接。我想到的第一个选项是使用第三方连接池。我选择了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");
    }
Run Code Online (Sandbox Code Playgroud)

二氯苯酚:

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");
    }
Run Code Online (Sandbox Code Playgroud)

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");
    }
Run Code Online (Sandbox Code Playgroud)

这是结果:

Max Pool size for c3p0 and dbcp=10
c3p0: 5534 milli secs
dbcp: 4807 milli secs
No Pooling: 2660 milli secs
Run Code Online (Sandbox Code Playgroud)

__

Max Pool size for c3p0 and dbcp=100
c3p0: 4937 milli secs
dbcp: 4798 milli secs
No Pooling: 2660 milli secs
Run Code Online (Sandbox Code Playgroud)

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

令人惊讶的是,无池方法比连接池方法快得多。虽然我认为当我们物理上关闭连接时,获取新连接肯定会更耗时。

那么,这是怎么回事?

EDIT_01:c3p0 和 dbcp 配置

c3p0:

cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(100);
cpds.setMaxStatements(1000);
Run Code Online (Sandbox Code Playgroud)

数据库控制协议:

basicDataSource.setMinIdle(5);
basicDataSource.setMaxIdle(30);
basicDataSource.setMaxTotal(100);
basicDataSource.setMaxOpenPreparedStatements(180);
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*man 5

c3p0 并不比门钉死。它很旧,但(在某种程度上)得到了积极维护。较新的替代方案是否更适合您的应用由您决定。

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

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

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

  • maven 组“c3p0”从未隶属于 c3p0 的作者(我),并放弃了他/她的维护。您将在 Maven Central 上的组名称“com.mchange”、工件名称“c3p0”下找到最近的 c3p0 (2认同)