JDBC的批量批量插入


本文部分轉載於:http://blog.itpub.net/29254281/viewspace-1151785/

http://www.cnblogs.com/chenjianjx/archive/2012/08/14/2637914.html  (這篇文章作者用的mysql驅動是5.1.12)

一. JDBC的批量插入

1.Mysql的驅動jar包選擇(重要)

使用MySQL的Batch批量處理,驅動jar包版本需要5.1.13或以上  我使用的驅動版本:mysql-connector-java-5.1.18-bin  (一開始我忽略掉這個jar包的條件要求了,使用的是mysql-connector-java-5.1.6-bin.jar在批處理插入時候效率和普通一樣)

2.測試表結構

測試表結構如下:
CREATE TABLE test (
  id int(11) DEFAULT NULL,
  name varchar(20) DEFAULT NULL
) ENGINE=InnoDB 

3.首先使用普通的方式插入100萬條數據,使用時間154901毫秒

程序如下:

 1     public static void generalInsert() throws ClassNotFoundException,SQLException{
 2         long start = System.currentTimeMillis();
 3         Class.forName("com.mysql.jdbc.Driver");
 4         Connection connection = DriverManager.getConnection(
 5                 "jdbc:mysql://127.0.0.1:3306/kxh", "root", "root");
 6 
 7         connection.setAutoCommit(false);
 8         PreparedStatement cmd = connection
 9                 .prepareStatement("insert into test values(?,?)");
10 
11         for (int i = 0; i < 1000000; i++) {
12             cmd.setInt(1, i);
13             cmd.setString(2, "test");
14             cmd.executeUpdate();
15         }
16         connection.commit();
17 
18         cmd.close();
19         connection.close();
20 
21         long end = System.currentTimeMillis();
22         System.out.println(end - start);//158918毫秒
23     }

4.使用批量處理100萬條數據,僅用24675毫秒,提升效果非常明顯,提升了6倍多.

程序如下:

 1     public static void batchInsert() throws ClassNotFoundException, SQLException{
 2         long start = System.currentTimeMillis();
 3         Class.forName("com.mysql.jdbc.Driver");
 4         Connection connection = DriverManager.getConnection(
 5                         "jdbc:mysql://127.0.0.1:3306/kxh?useServerPrepStmts=false&rewriteBatchedStatements=true",
 6                         "root", "root");
 7 
 8         connection.setAutoCommit(false);
 9         PreparedStatement cmd = connection
10                 .prepareStatement("insert into test1 values(?,?)");
11         
12         for (int i = 0; i < 1000000; i++) {//100萬條數據
13             cmd.setInt(1, i);
14             cmd.setString(2, "test");
15             cmd.addBatch();
16             if(i%1000==0){
17                 cmd.executeBatch();
18             }
19         }
20         cmd.executeBatch();
21         connection.commit();
22         
23         cmd.close();
24         connection.close();
25         
26         long end = System.currentTimeMillis();

27 System.out.println("批量插入需要時間:"+(end - start)); //批量插入需要時間:24675 28 }

 

MySQL 的驅動jar包在默認情況下會無視executeBatch()語句,把我們期望批量執行的一組sql語句拆散,一條一條地發給MySQL數據庫,直接造成較低的性能。

與Oracle不同的是,Mysql需要添加rewriteBatchedStatements=true的參數,才可以使用批量處理,否則還是使用逐條處理的方式。另外,有人說rewriteBatchedStatements只對INSERT有效,有人說它對UPDATE/DELETE也有效。

通過試驗結論是: 這個選項對INSERT/UPDATE/DELETE都有效,只不過對INSERT它為會預先重排一下SQL語句

5.開啟Myslq的查詢日志

①批量插入的日志:

開啟MySQL的查詢日志general_log(關於如何打開,查看mysql的日志請查看博客:http://www.cnblogs.com/DreamDrive/p/5761005.html),發現如下SQL
INSERT INTO test  
VALUES (11, 'test'), (12, 'test'), (13, 'test')......


上下兩行的id號碼正好相差1000,也就是代碼中設置的每1000次提交一次批處理.

②普通插入對應的日志:

如果使用普通的插入打印日志如下:

 

相對Oracle的批量處理,MySQL需要JDBC參數顯式開啟,並且對於JDBC驅動的版本也有要求。

 參數useServerPrepStmts=false,如果不開啟(useServerPrepStmts=false),使用com.mysql.jdbc.PreparedStatement進行本地SQL拼裝,最后送到db上就是已經替換了?后的最終SQL.

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM