2016-12-02 15 views
3

我需要創建一個約需要插入數據庫的50K記錄列表。Java列表v/s數據庫列表哪一個很貴?

我能想到的兩種方法是在性能

方面更好的辦法
  1. 存儲過程,它接受這些對象的名單,將它們插入Java和使用每一條記錄調用數據庫插入
  2. 建構列表MyBatis的
+0

無論哪種方式是好的,按我的知識,我會選擇2 MyBatis的一批去。 – PKR

+1

您應該爲每種方法確實設置測試用例,並查看數據,硬件,網絡等的性能。 – Boneist

+0

jdbc使用標準SQL直接支持批插入。雖然批處理實現不能保證被所有數據庫支持,但它受Oracle jdbc驅動程序支持,而Oracle PLSQL僅*受Oracle支持。另外,對於存儲過程,您將具有處理數組傳遞的額外複雜性。 – YoYo

回答

0

表現最好的將來自插入語句的批次,如下所示:

insert into my_table (c1, c2, c3) values 
    (v1, v2, v3), 
    (v4, v5, v6), 
    ... 

如果您將它分成50,000個插入語句,您將獲得更差的性能。插入語句越少越好。每個插入語句都需要mysql解析查詢,並獲取並釋放必要表上的鎖,更不用說啓動和提交事務。例如,如果您可以在500行的100個塊中完成此操作,則會削減49,900x這個開銷。

如果您想使用LOAD DATA INFILE命令,您甚至可以進一步提高性能,但這會使事情變得複雜一些,根據您的具體要求可能不值得。

+0

這是無效的oracle語法,儘管你可以通過各種方式實現類似的結果,例如'insert into my_table(c1,c2,c3)select double,union的所有v1,v2,v3所有從雙重聯合中選擇v4,v5,v6所有......'或'將所有值都插入my_table(c1,c2,c3)值(v1,v2,v3)到my_table(c1,c2,c3)值(v4,v5,v6)中... select * from dual 「一切都顯得更加冗長,但他們確實達到了將所有內容都保存在一個聲明中的預期結果。 – Sentinel

0

你最好的表現將是某種形式的批量插入不管是

多記錄插入:使用本地PL

insert into your_table(c1,c2,c3) 
select v1, v2, v3 from dual union all 
select v4, v5, v6 from dual union all 
... 
select vN, vO, vP from dual; 

insert all 
into your_table(c1,c2,c3) values (v1,v2,v3) 
into your_table(c1,c2,c3) values (v4,v5,v6) 
... 
into your_table(c1,c2,c3) values (vN,vO,vP) 
select * from dual; 

批量插入/ SQL集合:

FORALL i IN your_collection.first .. your_collection.last 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(your_collection(i).v1 
     , your_collection(i).v2 
     , your_collection(i).v3); 

FORALL i IN INDICES OF your_collection 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(your_collection(i).v1 
     , your_collection(i).v2 
     , your_collection(i).v3); 

或使用綁定陣列批量插入:

BEGIN 
    FORALL i IN :lower .. :upper 
    INSERT INTO your_table(c1,c2,c3) 
    VALUES(:v1(i), :v2(i), :v3(i)); 
END; 
+1

我懷疑提議的「多記錄插入」能否提供足夠的性能。該命令的大小可能爲1 MB(或100萬個字符)。只是發送和解析這樣的命令將需要一些時間。您很可能會額外努力發送CLOB等命令。 –

4

我想用PreparedStatement和批量插入是你最好的選擇。 PreparedStatement的好處在於,sql被緩存在RDBMS服務器上,批量插入可以以批處理的形式完成。

喜歡的東西:

private void doInsert(Connection conn, List<Data> data){ 
    String sql = "INSERT INTO T (A,B,C) VALUES (?,?,?)"; 
    PreparedStatement ps = conn.prepareStatement(sql); 
    int count = 0; 
    for(Data d : data) { 
     count++; 
     ps.setString(1, data.getA()); 
     ps.setString(2, data.getB()); 
     ps.setString(3, data.getC()); 
     ps.addBatch(); 
     if (count%1000 == 0) { 
      ps.executeBatch(); 
     } 
    } 
    ps.executeBatch(); 
    ps.close(); 
} 
+0

這真的是最好的答案,因爲它直接處理java'List',如何以可管理的批次分解它(並不總是一個單一的兆字節批是最好的),以及如何以標準jdbc方式處理批處理。 – YoYo

相關問題