JDBC主題
- JDBC初出茅廬-建立數據庫連接 https://www.7benshu.com/post/2020/03/21-1/
- JDBC小試牛刀-數據庫操作 https://www.7benshu.com/post/2020/03/21-2/
- JDBC略有建樹-二進制操作 https://www.7benshu.com/post/2020/03/21-3/
- JDBC出類拔萃-數據庫批量操作 https://www.7benshu.com/post/2020/03/21-4/
- JDBC百裡挑一|數據庫事務 https://www.7benshu.com/post/2020/03/22-1/
- JDBC卓越超群-DAO https://www.7benshu.com/post/2020/03/22-2/
介紹
在對關係型數據庫做大量數據輸入的時候, 不僅僅需要數據庫有吃的能力, 程序還要有插入的能力, 下面有幾個方式, 大家可以體驗下, 自己測試測試, 話不多說, 效果非常的明顯
批量執行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>
總結
以上的測試的耗時, 每次都會結果不一樣, 這個跟大家的電腦性能有關係, 看個趨勢就好了
數據庫的輸入的效率直接影響到業務的體驗和驗證, 提高的方式有很多, 架構也會不一樣, 多一個思路, 多一條路
閱讀更多 拉斐 的文章