JDBC出類拔萃-數據庫批量操作

JDBC主題

  1. JDBC初出茅廬-建立數據庫連接 https://www.7benshu.com/post/2020/03/21-1/
  2. JDBC小試牛刀-數據庫操作 https://www.7benshu.com/post/2020/03/21-2/
  3. JDBC略有建樹-二進制操作 https://www.7benshu.com/post/2020/03/21-3/
  4. JDBC出類拔萃-數據庫批量操作 https://www.7benshu.com/post/2020/03/21-4/
  5. JDBC百裡挑一|數據庫事務 https://www.7benshu.com/post/2020/03/22-1/
  6. JDBC卓越超群-DAO https://www.7benshu.com/post/2020/03/22-2/


JDBC出類拔萃-數據庫批量操作


介紹

在對關係型數據庫做大量數據輸入的時候, 不僅僅需要數據庫有吃的能力, 程序還要有插入的能力, 下面有幾個方式, 大家可以體驗下, 自己測試測試, 話不多說, 效果非常的明顯

批量執行SQL語句

當需要成批插入或者更新記錄時,可以採用Java的批量更新機制,這一機制允許多條語句一次性提交給數據庫批量處理。通常情況下比單獨提交處理更有效率

JDBC的批量處理語句包括下面三個方法:

  • addBatch(String):添加需要批量處理的SQL語句或是參數;
  • executeBatch():執行批量處理語句;
  • clearBatch():清空緩存的數據

通常我們會遇到兩種批量執行SQL語句的情況:

  • 多條SQL語句的批量處理;
  • 一個SQL語句的批量傳參;

高效的批量插入

舉例:向數據表中插入30000條數據

  • 數據庫中提供一個customers表。創建如下:
<code>CREATE TABLE customers(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);/<code>

方式一:使用Statement

<code>Connection conn = JDBCUtils.getConnection();
Statement st = conn.createStatement();

final Stopwatch started = Stopwatch.createStarted();

for (int i = 1; i <= 30000; i++) {
 String sql = String.format("insert into customers(name) values('name_%d')", i);
 st.executeUpdate(sql);
}

started.stop();
JDBCUtils.closeResource(conn, st);
System.out.println("耗時:"+started.elapsed().toMillis());

耗時:8880/<code>

方式二:使用PreparedStatement

<code>final Stopwatch started = Stopwatch.createStarted();

Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name)values(?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 1; i <= 30000; i++) {
 ps.setString(1, "name_" + i);
 ps.executeUpdate();

}
started.stop();
JDBCUtils.closeResource(conn, ps);
System.out.println("耗時:" + started.elapsed().toMillis());

耗時:8690/<code>

方式三

注意: JDBC驅動版本需要5.1.13或以上,才可以使用批處理

<code>/*
* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
* 修改2:mysql服務器默認是關閉批處理的,我們需要通過一個參數,讓mysql開啟批處理的支持。
* ?rewriteBatchedStatements=true 寫在配置文件的url後面
* 修改3:確認驅動版本,一定要注意版本
        <dependency>
           <groupid>mysql/<groupid>
           <artifactid>mysql-connector-java/<artifactid>
           <version>5.1.18/<version>
       /<dependency>
*
*/
final Stopwatch started = Stopwatch.createStarted();

Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name)values(?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 1; i <= 30000; i++) {
 ps.setString(1, "name_" + i);

 //1.加入批次
 ps.addBatch();
 if (i % 500 == 0) {
   //2.執行
   ps.executeBatch();
   //3.清空
   ps.clearBatch();
}
}

started.stop();
JDBCUtils.closeResource(conn, ps);
System.out.println("耗時:" + started.elapsed().toMillis());


耗時:995/<code>

方式四

<code>final Stopwatch started = Stopwatch.createStarted();

Connection conn = JDBCUtils.getConnection();

//1.設置為不自動提交數據
conn.setAutoCommit(false);

String sql = "insert into customers(name)values(?)";
PreparedStatement ps = conn.prepareStatement(sql);

for (int i = 1; i <= 1000000; i++) {
 ps.setString(1, "name_" + i);

 //1.加入批次
 ps.addBatch();

 if (i % 500 == 0) {
   //2.執行
   ps.executeBatch();
   //3.清空
   ps.clearBatch();
}
}

//2.提交數據
conn.commit();
started.stop();

JDBCUtils.closeResource(conn, ps);
System.out.println("耗時:" + started.elapsed().toMillis());

耗時:829
​/<code>

總結

以上的測試的耗時, 每次都會結果不一樣, 這個跟大家的電腦性能有關係, 看個趨勢就好了

數據庫的輸入的效率直接影響到業務的體驗和驗證, 提高的方式有很多, 架構也會不一樣, 多一個思路, 多一條路


分享到:


相關文章: