九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
第一周:JDBC中批量插入數(shù)據(jù)問題

在向數(shù)據(jù)庫中添加數(shù)據(jù)時,難免會遇到批量添加數(shù)據(jù)的問題。下面就是使用JDBC來實現(xiàn)批量插入的幾種方法。

準備工作:

  • 在MySQL5數(shù)據(jù)庫中創(chuàng)建一個names
  • 表中就兩個字段
    • id:主鍵,自增
    • name:varchar(25),保證長度夠用就行
CREATE TABLE names(
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(25)
);

方法一:

最直接的頻繁執(zhí)行SQL語句來插入

long start = System.currentTimeMillis();

// 獲取數(shù)據(jù)庫連接 
Connection conn= DriverManager.getConnection(url, user, password);
// SQL語句
String sql = "insert into names(name) values(?);";
// 預編譯SQL語句
PreparedStatement ps = conn.prepareStatement(sql);

// 批量插入 2萬 條數(shù)據(jù)
for (int i = 0; i < 20000; i++) {
    ps.setObject(1, "name_"+i); // 填充占位符?
    ps.execute(); // 每一條數(shù)據(jù)都執(zhí)行一次
}

long end = System.currentTimeMillis();

System.out.println("花費的時間為:" + (end - start)); // 花費的時間為:794551

// 關閉資源
ps.close();
conn.close();

方式二:

使用executeBatch()來批量插入數(shù)據(jù)

需要在數(shù)據(jù)庫連接的url中添加rewriteBatchedStatements=true字段,讓數(shù)據(jù)庫開啟批處理默認

long start = System.currentTimeMillis();

// 獲取數(shù)據(jù)庫連接 
Connection conn= DriverManager.getConnection(url, user, password);
// SQL語句
String sql = "insert into names(name) values(?)"; // 注意這里! 一定不要加結尾的分號;
// 預編譯SQL語句
PreparedStatement ps = conn.prepareStatement(sql);

// 批量插入 100萬 條數(shù)據(jù)
for (int i = 1; i <= 1000000; i++) {
    ps.setObject(1, "name_"+i);

    // 添加到同一batch中
    ps.addBatch();

    if (i % 500 == 0) { // 每批次夠500條才執(zhí)行 控制這個數(shù)也可以提高點速度
        // 執(zhí)行該batch的插入操作
        ps.executeBatch();

        // 清空已執(zhí)行的batch
        ps.clearBatch();
    }
}

long end = System.currentTimeMillis();

System.out.println("花費的時間為:" + (end - start)); // 花費的時間為:5177

// 關閉資源
ps.close();
conn.close();

注意:一定不要給SQL語句添加結尾的;。否則會拋異常。

java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '('name_2'),('name_3'),('name_4'),('name_5'),('name_6'),('name_7'),('name_8'),('n' at line 1...

至于原因,JDBC的源碼實在太晦澀了,看一會就前后連接不上了,所以筆者認為應該是由于在MySQL中批量插入的SQL語句的問題。

就是對于names表,直接在MySQL中用SQL語句來批量添加數(shù)據(jù)時,可以這樣

insert into names(`name`) values("name_1"), ("name_2"), ("name_3");

這行去掉;也能正常運行

但是如果這樣,注意分號

insert into names(`name`) values("name_1");, ("name_2"), ("name_3")

那么"name_1"插入表中,后面2和3沒有,并且MySQL拋異常。

? 那么或許在JDBC中,每次addBatch(),都是將要放在占位符?的數(shù)據(jù)先存在ArrayList中,當執(zhí)行executeBatch()時,遍歷ArrayList將第一個數(shù)據(jù)"name_1"放在SQL語句的?處,后續(xù)的全部構造成,("name_2")、,("name_3")的形式連接在這條SQL語句后面,最終構造成一個長的插入SQL語句,再執(zhí)行,完成批量插入。

即:

insert into names(`name`) values("name_1")
insert into names(`name`) values("name_1"), ("name_2")
insert into names(`name`) values("name_1"), ("name_2"), ("name_3")
insert into names(`name`) values("name_1"), ("name_2"), ("name_3")..., ("name_batchSize")

這樣由于執(zhí)行拼在一起的SQL就可以完成批量插入。

但是如果insert into names(name) values(?);結尾有個;,就變成這樣:

insert into names(`name`) values("name_1");
insert into names(`name`) values("name_1");, ("name_2")
insert into names(`name`) values("name_1");, ("name_2"), ("name_3")
insert into names(`name`) values("name_1");, ("name_2"), ("name_3")..., ("name_batchSize")

那么JDBC的對SQL語句的語法檢查語義檢查無法通過,就會拋異常。

數(shù)據(jù)庫中也不會有"name_1"這條數(shù)據(jù)。

以上是筆者的推測,并沒有通過JDBC源碼驗證。

方式三:

在方式二的基礎上再進一步優(yōu)化,除了改變一批次的容量(上面是500)外,還可以設置不允許自動提交數(shù)據(jù),改為手動提交數(shù)據(jù)。

// 設置不允許自動提交數(shù)據(jù)
conn.setAutoCommit(false); // 該行代碼放在獲取數(shù)據(jù)庫連接后

// ... 批量插入操作同上

// 提交數(shù)據(jù)
conn.commit(); // 在批量插入的for循環(huán)后

// 花費時間為:3954

另外,還有個executeLargeBatch()方法

當要總共要插入1億條數(shù)據(jù),并且一個batch為100萬

executeBatch()花費了413635毫秒

executeLargeBatch()花費了386389毫秒

emmm...可能不是單純替換著用的,哈哈哈!

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JDBC批處理
MySQL與Python
提升數(shù)據(jù)訪問層的性能(二)
通過JDBC進行簡單的增刪改查(以MySQL為例)
(2) Java SQL框架(java.sql.*)中常用接口詳解
javaweb使用JDBC進行批處理
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服