国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java實現jdbc批量插入數據

2019-11-26 14:22:22
字體:
來源:轉載
供稿:網友

首先介紹三種JDBC批量插入編程方法,進行比較,具體內容如下

JDBC批量插入主要用于數據導入和日志記錄因為日志一般都是先寫在文件下的等。
我用Mysql 5.1.5的JDBC driver 分別對三種比較常用的方法做了測試

方法一:使用PreparedStatement加批量的方法

try {  Class.forName("com.mysql.jdbc.Driver");  conn = DriverManager.getConnection(o_url, userName, password);  conn.setAutoCommit(false);  String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";  PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);  for(int x = 0; x < size; x++){   prest.setString(1, "192.168.1.1");   prest.setString(2, "localhost");   prest.setString(3, "20081009");   prest.setInt(4, 8);   prest.setString(5, "11111111");   prest.addBatch();  }  prest.executeBatch();  conn.commit();  conn.close(); } catch (SQLException ex) {  Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex); } catch (ClassNotFoundException ex) {  Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex); } 

說明下在建Statement的時候,后面兩個參數的意義:
第一個參數指定 ResultSet 的類型。其選項有:
TYPE_FORWARD_ONLY:缺省類型。只允許向前訪問一次,并且不會受到其他用戶對該數據庫所作更改的影響。
TYPE_SCROLL_INSENSITIVE:允許在列表中向前或向后移動,甚至可以進行特定定位,例如移至列表中的第四個記錄或者從當前位置向后移動兩個記錄。不會受到其他用戶對該數據庫所作更改的影響。
TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE 一樣,允許在記錄中定位。這種類型受到其他用戶所作更改的影響。如果用戶在執行完查詢之后刪除一個記錄,那個記錄將從 ResultSet 中消失。類似的,對數據值的更改也將反映在 ResultSet 中。
第二個參數設置 ResultSet 的并發性,該參數確定是否可以更新 ResultSet。其選項有:
CONCUR_READ_ONLY:這是缺省值,指定不可以更新
ResultSet CONCUR_UPDATABLE:指定可以更新 ResultSet

方法二:使用Statement加批量的方法

conn.setAutoCommit(false);  Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);  for(int x = 0; x < size; x++){  stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");  } stmt.executeBatch(); conn.commit(); 

方法三:直接使用Statement

conn.setAutoCommit(false); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,      ResultSet.CONCUR_READ_ONLY); for(int x = 0; x < size; x++){  stmt.execute("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')"); } conn.commit(); 

使用上述方法分別插入10萬條數據的平均測試時間為:
方法一:17.844s
方法二:18.421s
方法三:16.359s

可以看出JDBC的batch語句插入不但沒有性能提升,反而比沒有用batch的時候要慢,當然這可能跟JDBC具體驅動的實現方法有關。 附件中是我測試代碼,可以用來在自己電腦上跑一下。

在執行批量插入的時候最主要的是將自動提交取消,這樣不管是否用JDBC的batch語法應該都沒有關系。
conn.setAutoCommit(false) 

個人覺得第一種方法是最方便最實用的。

jdbc批量插入數據 例子講解:

最近做一個將excel數據導入數據庫的程序時,由于數據量大,準備采用jdbc的批量插入。于是用了preparedStatement.addBatch();當加入1w條數據時,再執行插入操作,preparedStatement.executeBatch()。我原以為這樣會很快,結果插入65536條數據一共花30多分鐘,完全出乎我的意料。于是問了一下同事,他們在處理這種大批量數據導入的時候是如何處理的,發現他們也是用的jdbc批量插入處理,但與我不同是:他們使用了con.setAutoCommit(false);然后再preparedStatement.executeBatch()之后,再執行con.commit();于是再試,什么叫奇跡?就是剛剛導入這些數據花了半小時,而加了這兩句話之后,現在只用了15秒鐘就完成了。于是去查查了原因,在網上發現了如下一段說明:

    * When importing data into InnoDB, make sure that MySQL does not have autocommit mode enabled because that

      requires a log flush to disk for every insert. To disable autocommit during your import operation, surround it with

      SET autocommit and COMMIT statements:

      SET autocommit=0;
     ... SQL import statements ...
     COMMIT;

第一次,正是因為沒有setAutoCommit(false);那么對于每一條insert語句,都會產生一條log寫入磁盤,所以雖然設置了批量插入,但其效果就像單條插入一樣,導致插入速度十分緩慢。

部分代碼如下:

String sql = "insert into table *****";con.setAutoCommit(false);ps = con.prepareStatement(sql);for(int i=1; i<65536; i++){ ps.addBatch(); // 1w條記錄插入一次 if (i % 10000 == 0){  ps.executeBatch();  con.commit(); }}// 最后插入不足1w條的數據ps.executeBatch();con.commit();

以上只是小菜,下面接著“上菜”:

1、測試批量寫入數據

 long start = System.currentTimeMillis(); DaoRecord daoRecord = new DaoRecord(); List<T> list = new ArrayList<T>(); for(int i = 1; i <= 1000; i++){  for(int j = 1; j <= 1000; j++){  T t = new T();  t.setI(i);  t.setJ(j);  list.add(t);  } } daoRecord.InsertBatch(list); System.out.println("耗時:" + (System.currentTimeMillis()-start)+"毫秒");

2、批量寫入數據測試

 public void InsertBatch(List<T> list){ String sql = "insert into t(go,back) values(?,?)"; DBHelper dbh = new DBHelper(sql); Connection conn = dbh.returnConn(); try {  conn.setAutoCommit(false);//注意此句一定要為false,原因見第一篇參考文獻  PreparedStatement ps = conn.prepareStatement(sql);  for(int i = 0; i < list.size(); i++){  ps.setInt(1, list.get(i).getI());  ps.setInt(2, list.get(i).getJ());  ps.addBatch();  if (i % 10000 == 0){   ps.executeBatch();   conn.commit();   }  }  ps.executeBatch();  conn.commit();  conn.close(); } catch (SQLException e) {  // TODO 自動生成的 catch 塊  e.printStackTrace(); } }

數據表:

實驗結果:

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 遂昌县| 会理县| 淄博市| 新宁县| 甘洛县| 神木县| 恩平市| 措美县| 江永县| 陆川县| 资兴市| 金乡县| 巢湖市| 图片| 黄龙县| 紫阳县| 伊春市| 乌什县| 祁东县| 西乌| 湘阴县| 孟连| 特克斯县| 石柱| 柘荣县| 屏山县| 天峻县| 昌江| 若尔盖县| 竹山县| 洪泽县| 本溪| 新郑市| 辉南县| 定兴县| 墨竹工卡县| 隆昌县| 班戈县| 丹凤县| 公安县| 孝感市|