这次所要做的测试是比较几种我们常用的数据库连接池的性能,他们分别是:c3p0 ,Proxool ,Druid ,Tomcat Jdbc Pool这四种,测试将采用统一的参数配置力求比较“公平”的体现统一水平下几种连接池的不同,有网友回复说测试不公平会互相干扰,那我就把代码分开,代码是死的人是活的,做事情不动脑只能吃别人剩下的,世界上没有绝对公平的事情,我在此只提供了一个思路,更多的测试还需要你自己去完成。
1.创建类TestDAO,封装统一的查询方法 :
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TestDAO { private final static String sql = "SELECT * FROM USER u WHERE u.USR_ID=9999"; public void query(Connection conn) { try { Statement st = conn.createStatement(); ResultSet result = st.executeQuery(sql); result.close(); st.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
2.创建测试类TestMain,其中包含:统一参数配置属性、获取各种连接池数据源方法、各种数据源调用方法等,下面分别是各种数据源的测试Main方法,开始测试之前做100次查询操作以初始化连接池并起到稳定测试结果作用:
(1)c3p0测试代码:
import java.beans.PropertyVetoException; import java.io.IOException; import java.sql.SQLException; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3p0Test { // 数据库驱动名称 final static String driver = "com.mysql.jdbc.Driver"; // 数据库连接地址 final static String jdbcUrl = "jdbc:mysql://192.168.0.1:3306/test"; // 数据库用户名 final static String user = "dba"; // 数据库密码 final static String passwd = "dba"; // 连接池初始化大小 final static int initialSize = 5; // 连接池最小空闲 final static int minPoolSize = 10; // 连接池最大连接数量 final static int maxPoolSize = 50; // 最小逐出时间,100秒 final static int maxIdleTime = 100000; // 连接失败重试次数 final static int retryAttempts = 10; // 当连接池连接耗尽时获取连接数 final static int acquireIncrement = 5; // c3p0数据源 final static ComboPooledDataSource c3p0DataSource = getC3p0DataSource(); // 查询次数 final static int count = 10; /** * 测试方式: 每种数据源配置信息尽量相同,以求结果更加准确 * 每种数据源做10次、100次、500次、1000次、2000次、4000次、8000次查询操作 每种查询重复100次,查看100次执行时间的波动图 * @param args * @throws IOException * @throws SQLException */ public static void main(String[] args) throws IOException, SQLException { TestDAO testDAO = new TestDAO(); System.out.println("查询次数为:" + count); System.out.println(); System.out.println("==========================c3p0 测试开始=========================="); // 测试c3p0 for (int i = 0; i < 100; i++) { queryC3p0(testDAO, c3p0DataSource, count); } System.out.println("==========================c3p0 测试结束=========================="); } /** * c3p0测试 * @param testDAO * @param ds * @param count * @throws SQLException */ public static void queryC3p0(TestDAO testDAO, ComboPooledDataSource ds, int count) throws SQLException { // 查询100次以初始化连接池 for (int i = 0; i < 100; i++) { testDAO.query(ds.getConnection()); } // 开始时间 long startMillis = System.currentTimeMillis(); // 循环查询 for (int i = 0; i < count; i++) { testDAO.query(ds.getConnection()); } // 结束时间 long endMillis = System.currentTimeMillis(); // 输出结束时间 System.out.println(endMillis - startMillis); } /** * 获取c3p0数据源 * @throws PropertyVetoException */ public static ComboPooledDataSource getC3p0DataSource() { // 设置参数 ComboPooledDataSource cpds = new ComboPooledDataSource(); try { cpds.setDriverClass(driver); } catch (PropertyVetoException e) { e.printStackTrace(); } cpds.setJdbcUrl(jdbcUrl); cpds.setUser(user); cpds.setPassword(passwd); cpds.setInitialPoolSize(initialSize); cpds.setMinPoolSize(minPoolSize); cpds.setMaxPoolSize(maxPoolSize); cpds.setMaxIdleTime(maxIdleTime); cpds.setAcquireRetryAttempts(retryAttempts); cpds.setAcquireIncrement(acquireIncrement); cpds.setTestConnectionOnCheckin(false); cpds.setTestConnectionOnCheckout(false); return cpds; } }
(2)Proxool测试代码:
import java.io.IOException; import java.sql.SQLException; import org.logicalcobwebs.proxool.ProxoolDataSource; public class ProxoolTest { // 数据库驱动名称 final static String driver = "com.mysql.jdbc.Driver"; // 数据库连接地址 final static String jdbcUrl = "jdbc:mysql://192.168.0.1:3306/test"; // 数据库用户名 final static String user = "dba"; // 数据库密码 final static String passwd = "dba"; // 连接池初始化大小 final static int initialSize = 5; // 连接池最小空闲 final static int minPoolSize = 10; // 连接池最大连接数量 final static int maxPoolSize = 50; // 最小逐出时间,100秒 final static int maxIdleTime = 100000; // 连接失败重试次数 final static int retryAttempts = 10; // 当连接池连接耗尽时获取连接数 final static int acquireIncrement = 5; // Proxool数据源 final static ProxoolDataSource proxoolDataSource = getProxoolDataSource(); // 查询次数 final static int count = 10; /** * 测试方式: 每种数据源配置信息尽量相同,以求结果更加准确 * 每种数据源做10次、100次、500次、1000次、2000次、4000次、8000次查询操作 每种查询重复100次,查看100次执行时间的波动图 * @param args * @throws IOException * @throws SQLException */ public static void main(String[] args) throws IOException, SQLException { TestDAO testDAO = new TestDAO(); System.out.println("查询次数为:" + count); System.out.println(); System.out.println("==========================Proxool 测试开始=========================="); // 测试Proxool for (int i = 0; i < 100; i++) { queryProxxool(testDAO, proxoolDataSource, count); } System.out.println("==========================Proxool 测试结束=========================="); } /** * Proxxool测试 * @param testDAO * @param ds * @param count * @throws SQLException */ public static void queryProxxool(TestDAO testDAO, ProxoolDataSource ds, int count) throws SQLException { // 查询100次以初始化连接池 for (int i = 0; i < 100; i++) { testDAO.query(ds.getConnection()); } // 开始时间 long startMillis = System.currentTimeMillis(); // 循环查询 for (int i = 0; i < count; i++) { testDAO.query(ds.getConnection()); } // 结束时间 long endMillis = System.currentTimeMillis(); // 输出结束时间 System.out.println(endMillis - startMillis); } /** * 获取Proxool数据源 * @return */ public static ProxoolDataSource getProxoolDataSource() { ProxoolDataSource pds = new ProxoolDataSource(); pds.setAlias("mysql"); pds.setUser(user); pds.setPassword(passwd); pds.setDriverUrl(jdbcUrl); pds.setDriver(driver); pds.setMaximumActiveTime(maxIdleTime); pds.setMaximumConnectionCount(maxPoolSize); pds.setMinimumConnectionCount(initialSize); pds.setPrototypeCount(minPoolSize); pds.setTestBeforeUse(false); pds.setTestAfterUse(false); return pds; } }
(3)Druid测试代码:
import java.io.IOException; import java.sql.SQLException; import com.alibaba.druid.pool.DruidDataSource; public class DruidTest { // 数据库驱动名称 final static String driver = "com.mysql.jdbc.Driver"; // 数据库连接地址 final static String jdbcUrl = "jdbc:mysql://192.168.0.1:3306/test"; // 数据库用户名 final static String user = "dba"; // 数据库密码 final static String passwd = "dba"; // 连接池初始化大小 final static int initialSize = 5; // 连接池最小空闲 final static int minPoolSize = 10; // 连接池最大连接数量 final static int maxPoolSize = 50; // 最小逐出时间,100秒 final static int maxIdleTime = 100000; // 连接失败重试次数 final static int retryAttempts = 10; // 当连接池连接耗尽时获取连接数 final static int acquireIncrement = 5; // Druid数据源 final static DruidDataSource druidDataSource = getDruidDataSource(); // 查询次数 final static int count = 10; /** * 测试方式: 每种数据源配置信息尽量相同,以求结果更加准确 * 每种数据源做10次、100次、500次、1000次、2000次、4000次、8000次查询操作 每种查询重复100次,查看100次执行时间的波动图 * @param args * @throws IOException * @throws SQLException */ public static void main(String[] args) throws IOException, SQLException { TestDAO testDAO = new TestDAO(); System.out.println("查询次数为:" + count); System.out.println(); System.out.println("==========================Druid 测试开始=========================="); // 测试Druid for (int i = 0; i < 100; i++) { queryDruid(testDAO, druidDataSource, count); } System.out.println("==========================Druid 测试结束=========================="); } /** * Druid测试 * @param testDAO * @param ds * @param count * @throws SQLException */ public static void queryDruid(TestDAO testDAO, DruidDataSource ds, int count) throws SQLException { // 查询100次以初始化连接池 for (int i = 0; i < 100; i++) { testDAO.query(ds.getConnection()); } // 开始时间 long startMillis = System.currentTimeMillis(); // 循环查询 for (int i = 0; i < count; i++) { testDAO.query(ds.getConnection()); } // 结束时间 long endMillis = System.currentTimeMillis(); // 输出结束时间 System.out.println(endMillis - startMillis); } /** * 获取Druid数据源 * @return */ public static DruidDataSource getDruidDataSource() { DruidDataSource dds = new DruidDataSource(); dds.setUsername(user); dds.setUrl(jdbcUrl); dds.setPassword(passwd); dds.setDriverClassName(driver); dds.setInitialSize(initialSize); dds.setMaxActive(maxPoolSize); dds.setMaxWait(maxIdleTime); dds.setTestWhileIdle(false); dds.setTestOnReturn(false); dds.setTestOnBorrow(false); return dds; } }
(4)Tomcat Jdbc Pool测试代码:
import java.io.IOException; import java.sql.SQLException; import org.apache.tomcat.jdbc.pool.DataSource; public class TomcatTest { // 数据库驱动名称 final static String driver = "com.mysql.jdbc.Driver"; // 数据库连接地址 final static String jdbcUrl = "jdbc:mysql://192.168.0.1:3306/test"; // 数据库用户名 final static String user = "dba"; // 数据库密码 final static String passwd = "dba"; // 连接池初始化大小 final static int initialSize = 5; // 连接池最小空闲 final static int minPoolSize = 10; // 连接池最大连接数量 final static int maxPoolSize = 50; // 最小逐出时间,100秒 final static int maxIdleTime = 100000; // 连接失败重试次数 final static int retryAttempts = 10; // 当连接池连接耗尽时获取连接数 final static int acquireIncrement = 5; // Tomcat Jdbc Pool数据源 final static DataSource tomcatDataSource = getTomcatDataSource(); // 查询次数 final static int count = 100; /** * 测试方式: 每种数据源配置信息尽量相同,以求结果更加准确 * 每种数据源做10次、100次、500次、1000次、2000次、4000次、8000次查询操作 每种查询重复100次,查看100次执行时间的波动图 * @param args * @throws IOException * @throws SQLException */ public static void main(String[] args) throws IOException, SQLException { TestDAO testDAO = new TestDAO(); System.out.println("查询次数为:" + count); System.out.println(); System.out.println("==========================Tomcat Jdbc Pool 测试开始=========================="); // 测试Tomcat Jdbc Pool for (int i = 0; i < 100; i++) { queryTomcatJDBC(testDAO, tomcatDataSource, count); } System.out.println("==========================Tomcat Jdbc Pool 测试结束=========================="); } /** * Tomcat Jdbc Pool测试 * @param testDAO * @param ds * @param count * @throws SQLException */ public static void queryTomcatJDBC(TestDAO testDAO, DataSource ds, int count) throws SQLException { // 查询100次以初始化连接池 for (int i = 0; i < 100; i++) { testDAO.query(ds.getConnection()); } // 开始时间 long startMillis = System.currentTimeMillis(); // 循环查询 for (int i = 0; i < count; i++) { testDAO.query(ds.getConnection()); } // 结束时间 long endMillis = System.currentTimeMillis(); // 输出结束时间 System.out.println(endMillis - startMillis); } /** * 获取Apache tomcat jdbc pool数据源 * @return */ public static DataSource getTomcatDataSource() { DataSource ds = new DataSource(); ds.setUrl(jdbcUrl); ds.setUsername(user); ds.setPassword(passwd); ds.setDriverClassName(driver); ds.setInitialSize(initialSize); ds.setMaxIdle(minPoolSize); ds.setMaxActive(maxPoolSize); ds.setTestWhileIdle(false); ds.setTestOnBorrow(false); ds.setTestOnConnect(false); ds.setTestOnReturn(false); return ds; } }
3.将测试结果粘贴到excel中,生成图表进行对比,可以很直观的看出几种数据源的性能差异,本文底部有此次测试的结果文档。
以下就是此次测试结果(本结果只供参考,更具体更准确的测试可以自行进行):
1.测试次数为10次时:
平均用时(单位:毫秒):
c3p0 | 32.26 |
Proxool | 33.42 |
Druid | 30.43 |
Tomcat Jdbc Pool | 37.61 |
2.测试次数为100次时:
平均用时(单位:毫秒):
c3p0 | 409.94 |
Proxool | 447.49 |
Druid | 382.7 |
Tomcat Jdbc Pool | 386.3 |
平均用时(单位:毫秒):
c3p0 | 1700.95 |
Proxool | 2053.85 |
Druid | 1777.36 |
Tomcat Jdbc Pool | 1749.02 |
4.测试次数为1000次时:
平均用时(单位:毫秒):
c3p0 | 3549.29 |
Proxool | 3435.8 |
Druid | 3167.59 |
Tomcat Jdbc Pool | 3162.25 |
因为测试耗时很长,所以我只做到了1000次查询测试,感兴趣的朋友可以继续更大规模的测试或修改相应参数来符合项目自身情况,这里不比去追究测试数据的准确性,比较测试程度还不够,且存在很大的偶然性,大家可以修改以上代码进行更精准的测试,只需要将数据导入到本文末尾的excel表格中即可生成相应测试图表。
很多人总是会回复在问“你的测试准不准啊?”,“你的测试一点都不准!”等等,其实我想说的是:不要太在意别人的结果,重要的是自己去做!