轉自https://blog.csdn.net/q6834850/article/details/73726707?tdsourcetag=s_pctim_aiomsg
采用JDBC批處理(開啟事務、無事務)
采用JDBC批處理時需要注意一下幾點:
1、在URL連接時需要開啟批處理、以及預編譯
String url = “jdbc:mysql://localhost:3306/User?rewriteBatched
-Statements=true&useServerPrepStmts=false”;2、PreparedStatement預處理sql語句必須放在循環體外
代碼如下:
private long begin = 33112001;//起始id private long end = begin+100000;//每次循環插入的數據量 private String url = "jdbc:mysql://localhost:3306/bigdata?useServerPrepStmts=false&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8"; private String user = "root"; private String password = "0203"; @org.junit.Test public void insertBigData() { //定義連接、statement對象 Connection conn = null; PreparedStatement pstm = null; try { //加載jdbc驅動 Class.forName("com.mysql.jdbc.Driver"); //連接mysql conn = DriverManager.getConnection(url, user, password); //將自動提交關閉 // conn.setAutoCommit(false); //編寫sql String sql = "INSERT INTO person VALUES (?,?,?,?,?,?,?)"; //預編譯sql pstm = conn.prepareStatement(sql); //開始總計時 long bTime1 = System.currentTimeMillis(); //循環10次,每次十萬數據,一共1000萬 for(int i=0;i<10;i++) { //開啟分段計時,計1W數據耗時 long bTime = System.currentTimeMillis(); //開始循環 while (begin < end) { //賦值 pstm.setLong(1, begin); pstm.setString(2, RandomValue.getChineseName()); pstm.setString(3, RandomValue.name_sex); pstm.setInt(4, RandomValue.getNum(1, 100)); pstm.setString(5, RandomValue.getEmail(4, 15)); pstm.setString(6, RandomValue.getTel()); pstm.setString(7, RandomValue.getRoad()); //添加到同一個批處理中 pstm.addBatch(); begin++; } //執行批處理 pstm.executeBatch(); // //提交事務 // conn.commit(); //邊界值自增10W end += 100000; //關閉分段計時 long eTime = System.currentTimeMillis(); //輸出 System.out.println("成功插入10W條數據耗時:"+(eTime-bTime)); } //關閉總計時 long eTime1 = System.currentTimeMillis(); //輸出 System.out.println("插入100W數據共耗時:"+(eTime1-bTime1)); } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } }
接着測試
開啟事務,每次循環插入10W條數據,循環10次,一共100W條數據。結果如下圖:
成功插入10W條數據耗時:3482
成功插入10W條數據耗時:1776
成功插入10W條數據耗時:1979
成功插入10W條數據耗時:1730
成功插入10W條數據耗時:1643
成功插入10W條數據耗時:1665
成功插入10W條數據耗時:1622
成功插入10W條數據耗時:1624
成功插入10W條數據耗時:1779
成功插入10W條數據耗時:1698
插入100W數據共耗時:19003
實驗結果:
使用JDBC批處理,開啟事務,平均每 1.9 秒插入 十萬 條數據
3 總結
能夠看到,在開啟事務下 JDBC直接處理 和 JDBC批處理 均耗時更短。
Mybatis 輕量級框架插入 , mybatis在我這次實驗被黑的可慘了,哈哈。實際開啟事務以后,差距不會這么大(差距10倍)。大家有興趣的可以接着去測試
JDBC直接處理,在本次實驗,開啟事務和關閉事務,耗時差距5倍左右,並且這個倍數會隨着數據量的增大而增大。因為在未開啟事務時,更新10000條數據,就得訪問數據庫10000次。導致每次操作都需要操作一次數據庫。
JDBC批處理,在本次實驗,開啟事務與關閉事務,耗時差距很微小(后面會增加測試,加大這個數值的差距)。但是能夠看到開啟事務以后,速度還是有提升。結論,設計到大量單條數據的插入,使用JDBC批處理和事務混合速度最快
實測使用批處理+事務混合插入1億條數據耗時:174756毫秒
借用:
分別是:
不用批處理,不用事務; 只用批處理,不用事務; 只用事務,不用批處理; 既用事務,也用批處理;(很明顯,這個最快,所以建議在處理大批量的數據時,同時使用批處理和事務)