分享

为什么PrepareStatement和Batch性能相差不大,欢迎分析 - Java综合...

 昵称6312524 2011-04-19
今天在Javaeye论坛上看到有位网友得出结论:主题:Hibernate性能 - 30倍普通SQL操作 - 探讨 地址:[url]http://www./topic/743613 [/url].贴子中说JDBC测试插入10000条数据花费时间:Total spent 249531毫秒.而且贴子还说:这个时间我觉得是比较合理的执行一条SQL花费25毫秒左右,之前有关效率方面的测试和这个结果差不多。

不知他在什么配置情况下操作。因为结果是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
================================

代码如下:

Java代码 复制代码 收藏代码
  1. package test;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. import com.fastbo.util.Clock;
  7. import com.fastbo.util.ConnectionFactory;
  8. import com.fastbo.util.DbUtil;
  9. /**
  10. * Description: Jdbc相关性能测试,batch处理,PrepareStatement,Statement等。
  11. *
  12. * <p>
  13. * Mysql数据库:表结构为简单的id,name(varchar:255),type(varchar:255)字段,id自增
  14. * </p>
  15. *
  16. * @author Peter Wei Email: <a href="mailto:weigbo@163.com">weigbo@163.com </a>
  17. *
  18. * @version 1.0 2010-8-21
  19. */
  20. public class JdbcTest {
  21. /**
  22. * 测试数据量
  23. */
  24. public static int TEST_NUM = 10000;
  25. /**
  26. * 批处理大小
  27. */
  28. public static int BATCH_SIZE = 300;
  29. /**
  30. * 清空数据表
  31. *
  32. * @param con
  33. */
  34. public static void clear(Connection con) {
  35. PreparedStatement ps = null;
  36. StringBuffer buff = new StringBuffer();
  37. try {
  38. buff.append("truncate table bobo");
  39. ps = con.prepareStatement(buff.toString());
  40. ps.executeUpdate();
  41. System.out.println("清空表");
  42. } catch (SQLException e) {
  43. e.printStackTrace();
  44. } finally {
  45. DbUtil.close(ps);
  46. }
  47. }
  48. /**
  49. * 普通的Statement插入数据
  50. *
  51. * @param con
  52. */
  53. public static int add(Connection con) {
  54. Statement stmt = null;
  55. int num = 0;
  56. String sql = "insert into bobo(name,type) values('Peter Wei','test')";
  57. try {
  58. stmt = con.createStatement();
  59. for (int i = 0; i < TEST_NUM; i++) {
  60. num += stmt.executeUpdate(sql);
  61. }
  62. System.out.println("插入数据量:" + num);
  63. } catch (SQLException e) {
  64. e.printStackTrace();
  65. } finally {
  66. DbUtil.close(stmt);
  67. }
  68. return num;
  69. }
  70. /**
  71. * 用PrepareStatement插入数据
  72. *
  73. * @param con
  74. */
  75. public static void addByPrepareStatement(Connection con) {
  76. PreparedStatement ps = null;
  77. StringBuffer buff = new StringBuffer();
  78. int num = 0;
  79. try {
  80. buff.append("insert into bobo(name,type)");
  81. buff.append(" values(?,?)");
  82. ps = con.prepareStatement(buff.toString());
  83. con.setAutoCommit(false);
  84. for (int i = 0; i < TEST_NUM; i++) {
  85. int index = 1;
  86. ps.setString(index++, "Peter Wei");
  87. ps.setString(index++, "test");
  88. num += ps.executeUpdate();
  89. }
  90. con.commit();
  91. con.setAutoCommit(true);
  92. System.out.println("插入数据量:" + num);
  93. } catch (SQLException e) {
  94. e.printStackTrace();
  95. } finally {
  96. DbUtil.close(ps);
  97. }
  98. }
  99. /**
  100. * 用批处理插入数据
  101. *
  102. * @param con
  103. */
  104. public static void addByBatch(Connection con) {
  105. PreparedStatement ps = null;
  106. StringBuffer buff = new StringBuffer();
  107. int sum = 0;
  108. int[] num = null;
  109. try {
  110. buff.append("insert into bobo(name,type) values(?,?)");
  111. con.setAutoCommit(false);
  112. ps = con.prepareStatement(buff.toString());
  113. for (int i = 0; i < TEST_NUM; i++) {
  114. int index = 1;
  115. ps.setString(index++, "Peter Wei");
  116. ps.setString(index++, "test");
  117. ps.addBatch();
  118. if (i != 0 && i % BATCH_SIZE == 0) {
  119. num = ps.executeBatch();
  120. sum += num.length;
  121. con.commit();
  122. // System.out.println("batch:" + i);
  123. }
  124. }
  125. num = ps.executeBatch();
  126. sum += num.length;
  127. con.commit();
  128. con.setAutoCommit(true);
  129. System.out.println("批量更新成功 " + sum + " 条记录!");
  130. } catch (SQLException e) {
  131. e.printStackTrace();
  132. } finally {
  133. DbUtil.close(ps);
  134. }
  135. }
  136. public static void main(String[] args) {
  137. Connection con = ConnectionFactory.getConnection();
  138. clear(con);
  139. Clock c = new Clock();
  140. // 普通的Statement插入数据
  141. System.out.println("普通的Statement插入数据:");
  142. c.start();
  143. add(con);
  144. c.stop();
  145. System.out.println(c.toString());
  146. c.readMilli();
  147. System.out.println(c.read());
  148. System.out.println("================================");
  149. clear(con);
  150. // 通过PrepareStatement插入数据
  151. System.out.println("通过PrepareStatement插入数据:");
  152. c = new Clock();
  153. c.start();
  154. addByPrepareStatement(con);
  155. c.stop();
  156. System.out.println(c.toString());
  157. c.readMilli();
  158. System.out.println(c.read());
  159. System.out.println("================================");
  160. clear(con);
  161. // 用批处理插入数据
  162. System.out.println("用批处理插入数据:");
  163. c = new Clock();
  164. c.start();
  165. addByBatch(con);
  166. c.stop();
  167. System.out.println(c.toString());
  168. c.readMilli();
  169. System.out.println(c.read());
  170. System.out.println("================================");
  171. }
  172. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多