精华帖 (9) :: 良好帖 (0) :: 新手帖 (12) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-08-21
最后修改:2010-08-22
不知他在什么配置情况下操作。因为结果是4分多钟。对于此结论很是惊奇,因为以前做过数据同步的东西,于是马上亲自验证,数据库和测试参数和他的都一样。 先说结果:我的测试最慢的只用了2.6秒。Statement最慢,PrepareStaement快了5秒钟,Batch和PrepareStatement并没有实质性的提高,只是一小点(这个倒是让我奇怪)。从一万到十万数据量都做过测试,但变化不大。我一直认为Batch会提高不少数量级的,可是结果让我失望,也不知哪写得不对,大家可以分析一下代码。 ------------------------------------------------------------ 结果已出来,是默认的Mysql不是InnoDB,所以没有事务,所以之前测的没有本质变化。实际上在事务下,Batch能提高数量级的提高。 直接pringln 10000的一些对比数据: 清空表 普通的Statement插入数据: 插入数据量:10000 <运行时间: 2.656 秒> 运行时间:2656 毫秒 2.656 ================================ 清空表 通过PrepareStatement插入数据: 插入数据量:10000 <运行时间: 2.156 秒> 运行时间:2156 毫秒 2.156 ================================ 清空表 用批处理插入数据: 批量更新成功 10000 条记录! <运行时间: 2.078 秒> 运行时间:2078 毫秒 2.078 ================================ 代码如下: package test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import com.fastbo.util.Clock; import com.fastbo.util.ConnectionFactory; import com.fastbo.util.DbUtil; /** * Description: Jdbc相关性能测试,batch处理,PrepareStatement,Statement等。 * * <p> * Mysql数据库:表结构为简单的id,name(varchar:255),type(varchar:255)字段,id自增 * </p> * * @author Peter Wei Email: <a href="mailto:weigbo@163.com">weigbo@163.com </a> * * @version 1.0 2010-8-21 */ public class JdbcTest { /** * 测试数据量 */ public static int TEST_NUM = 10000; /** * 批处理大小 */ public static int BATCH_SIZE = 300; /** * 清空数据表 * * @param con */ public static void clear(Connection con) { PreparedStatement ps = null; StringBuffer buff = new StringBuffer(); try { buff.append("truncate table bobo"); ps = con.prepareStatement(buff.toString()); ps.executeUpdate(); System.out.println("清空表"); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtil.close(ps); } } /** * 普通的Statement插入数据 * * @param con */ public static int add(Connection con) { Statement stmt = null; int num = 0; String sql = "insert into bobo(name,type) values('Peter Wei','test')"; try { stmt = con.createStatement(); for (int i = 0; i < TEST_NUM; i++) { num += stmt.executeUpdate(sql); } System.out.println("插入数据量:" + num); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtil.close(stmt); } return num; } /** * 用PrepareStatement插入数据 * * @param con */ public static void addByPrepareStatement(Connection con) { PreparedStatement ps = null; StringBuffer buff = new StringBuffer(); int num = 0; try { buff.append("insert into bobo(name,type)"); buff.append(" values(?,?)"); ps = con.prepareStatement(buff.toString()); con.setAutoCommit(false); for (int i = 0; i < TEST_NUM; i++) { int index = 1; ps.setString(index++, "Peter Wei"); ps.setString(index++, "test"); num += ps.executeUpdate(); } con.commit(); con.setAutoCommit(true); System.out.println("插入数据量:" + num); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtil.close(ps); } } /** * 用批处理插入数据 * * @param con */ public static void addByBatch(Connection con) { PreparedStatement ps = null; StringBuffer buff = new StringBuffer(); int sum = 0; int[] num = null; try { buff.append("insert into bobo(name,type) values(?,?)"); con.setAutoCommit(false); ps = con.prepareStatement(buff.toString()); for (int i = 0; i < TEST_NUM; i++) { int index = 1; ps.setString(index++, "Peter Wei"); ps.setString(index++, "test"); ps.addBatch(); if (i != 0 && i % BATCH_SIZE == 0) { num = ps.executeBatch(); sum += num.length; con.commit(); // System.out.println("batch:" + i); } } num = ps.executeBatch(); sum += num.length; con.commit(); con.setAutoCommit(true); System.out.println("批量更新成功 " + sum + " 条记录!"); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtil.close(ps); } } public static void main(String[] args) { Connection con = ConnectionFactory.getConnection(); clear(con); Clock c = new Clock(); // 普通的Statement插入数据 System.out.println("普通的Statement插入数据:"); c.start(); add(con); c.stop(); System.out.println(c.toString()); c.readMilli(); System.out.println(c.read()); System.out.println("================================"); clear(con); // 通过PrepareStatement插入数据 System.out.println("通过PrepareStatement插入数据:"); c = new Clock(); c.start(); addByPrepareStatement(con); c.stop(); System.out.println(c.toString()); c.readMilli(); System.out.println(c.read()); System.out.println("================================"); clear(con); // 用批处理插入数据 System.out.println("用批处理插入数据:"); c = new Clock(); c.start(); addByBatch(con); c.stop(); System.out.println(c.toString()); c.readMilli(); System.out.println(c.read()); System.out.println("================================"); } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-08-22
最后修改:2010-08-22
你的例子我测了一下,环境是SQL2000和JTDS。
结果分别是: 清空表 普通的Statement插入数据: 插入数据量:10000 3656 ================================ 清空表 通过PrepareStatement插入数据: 插入数据量:10000 3985 ================================ 清空表 用批处理插入数据: 批量更新成功 10000 条记录! 296 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 另外,我又试了一下用Statement作批处理插入时的情况,结果是: 清空表 用批处理2插入数据: 批量更新成功 10000 条记录! 297 ================================ 用Statement,不使用批处理,但使用批量commit的时候, 代码如下: con.setAutoCommit(false); stmt = con.createStatement(); for (int i = 0; i < TEST_NUM; i++) { stmt.execute(sql); sum++; if (i != 0 && i % BATCH_SIZE == 0) { con.commit(); } } 结果是: 清空表 用批处理3插入数据: 批量更新成功 10000 条记录! 968 ================================ |
|
返回顶楼 | |
发表时间:2010-08-22
用Statement,使用批处理,但autoCommit=true的时候,
结果如下: 清空表 用批处理4插入数据: 批量更新成功 10000 条记录! 1719 ================================ 按上面的测试,影响性能最大的应该是 事务的大小, 批处理的影响次之, PreparedStatement和Statement似乎区别不是很大 |
|
返回顶楼 | |
发表时间:2010-08-22
最后修改:2010-08-22
清空表
通过PrepareStatement插入数据: 插入数据量:10000 3985 ================================ 清空表 用批处理插入数据: 批量更新成功 10000 条记录! 296 ========================= 你确定用我相同的代码,批处理和preparestatement相差有10倍?难道是mysql和sql server数据库内部的机制问题。我有空用oracle测一下。难道是mysql setCommit(false),不起作用,奇怪了。 |
|
返回顶楼 | |
发表时间:2010-08-22
跟驱动的jdbc实现有直接关系,
所以各个数据库是不同的。 and 跟每条记录的数据量和复杂度也有关系。 |
|
返回顶楼 | |
发表时间:2010-08-22
peterwei 写道 清空表
通过PrepareStatement插入数据: 插入数据量:10000 3985 ================================ 清空表 用批处理插入数据: 批量更新成功 10000 条记录! 296 ========================= 你确定用我相同的代码,批处理和preparestatement相差有10倍?难道是mysql和sql server数据库内部的机制问题。我有空用oracle测一下。难道是mysql setCommit(false),不起作用,奇怪了。 ^ ^ 如果mysql的表不是事务的,那应该测试不出多少差异 |
|
返回顶楼 | |
发表时间:2010-08-22
找不到以前的测试数据量
pcserver,redhat5.4,oracle10g,jdk6,表中有10几个字段, 批量2000,插入效率约每秒3w+,大概是逐条插入的近10倍。 不过用plsql写procedures的话,是每秒7w+, 这说明oracle的native驱动还是比jdbc驱动强太多。 |
|
返回顶楼 | |
发表时间:2010-08-22
最后修改:2010-08-22
dotaking 写道 找不到以前的测试数据量
pcserver,redhat5.4,oracle10g,jdk6,表中有10几个字段, 批量2000,插入效率约每秒3w+,大概是逐条插入的近10倍。 不过用plsql写procedures的话,是每秒7w+, 这说明oracle的native驱动还是比jdbc驱动强太多。 不是你说的那个原因。 如果是procedure的话,很多操作直接是在DB Server端进行的,客户端调用,省却了很多网络传输的时间和资源开销。 |
|
返回顶楼 | |
发表时间:2010-08-22
Batch和PrepareStatement比Statement并没有实质性的提高,只是一小点(这个倒是让我奇怪)。
-------------------------------------- ok,结果出来了。确实是setAutoCommit(false);不起作用。原来默认装的mysql数据库不是InnoDB,而是MyISAM,所以是没有事务的。楼上的skzr.org说得对。改数据库后,重测了一下,得到我想要的结果。 清空表 普通的Statement插入数据: 插入数据量:10000 <运行时间: 17.828 秒> 运行时间:17828 毫秒 17.828 ================================ 清空表 通过PrepareStatement插入数据: 插入数据量:10000 <运行时间: 2.594 秒> 运行时间:2594 毫秒 2.594 ================================ 清空表 用批处理插入数据: 批量更新成功 10000 条记录! <运行时间: 2.187 秒> 运行时间:2187 毫秒 2.187 ================================ |
|
返回顶楼 | |
发表时间:2010-08-22
最后修改:2010-08-22
murainwood 写道 dotaking 写道 找不到以前的测试数据量
pcserver,redhat5.4,oracle10g,jdk6,表中有10几个字段, 批量2000,插入效率约每秒3w+,大概是逐条插入的近10倍。 不过用plsql写procedures的话,是每秒7w+, 这说明oracle的native驱动还是比jdbc驱动强太多。 不是你说的那个原因。 如果是procedure的话,很多操作直接是在DB Server端进行的,客户端调用,省却了很多网络传输的时间和资源开销。 局域网,网络不是瓶颈。 而且,我说的最后两句,是另外的东西。前面两句才是批量和逐条的效率比较。 只是我找不到测试报告了。~ :( |
|
返回顶楼 | |