SQL Server的JDBC连接池:DBCP与C3P0 vs No Pooling

时间:2016-08-22 08:49:16

标签: sql-server jdbc connection-pooling c3p0 apache-commons-dbcp

我得到了这个Java webapp,它恰好与SQL Server数据库进行了太多的沟通。我想决定如何以有效的方式管理与此DB的连接。想到的第一个选择是使用连接池第三方。我选择了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);

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

1 个答案:

答案 0 :(得分:4)

c3p0不是doornail的deader。它虽旧,但(有些)积极维护。更新的替代品是否更适合您的应用需要您自行决定。

您使用的是什么版本的c3p0?如果你认为它比一个门钉更令人沮丧,你使用旧版本吗?你应该使用0.9.5.2。

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

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