2015-06-20 107 views
0

我有一個表在某些字段上具有唯一約束。我需要在此表中插入大量記錄。爲了讓它更快,我使用JDBC進行批量更新(驅動程序版本爲8.3-603)。 有沒有辦法做到以下幾點:JDBC - PostgreSQL - 批量插入+唯一索引

  • 每批執行我需要編寫到表中所有這一切不違反唯一索引批記錄;

  • 每批執行我需要得到從沒有插入DB批的記錄,所以我可以拯救「錯誤」的記錄

+0

不,這是不可能的。您需要先將行寫入中間表(不帶constraitns),然後使用SQL將有效的行復制到目標表中。順便說一句:你爲​​什麼使用這樣一個過時的驅動程序版本? –

+0

我想使用較新的版本,但這不是我的決定:( 我怎樣才能使用中間表更高效?逐行復制並刪除複製,然後在完成時讀取該表中剩下的記錄? –

+0

查看「bulk upsert」 –

回答

1

這樣做會是這樣的最有效的方法:

  • 創建一個臨時表具有相同結構的目標表,但沒有唯一約束
  • 批量插入所有行成分期表。最有效的方法是使用copy或使用CopyManager(雖然我不知道這是否已經在你的古老的驅動程序版本不支持

一旦做到這一點,你複製的有效行到目標表:

insert into target_table(id, col_1, col_2) 
select id, col_1, col_2 
from staging_table 
where not exists (select * 
        from target_table 
        where target_table.id = staging_table.id); 

注意的是,以上併發安全!如果其他進程做同樣的事情,你可能仍然得到唯一鍵衝突。爲了防止這種情況,你需要鎖定目標表。

如果要刪除複製行,你能做到這一點使用可寫CTE:在staging_table.id

with inserted as (
    insert into target_table(id, col_1, col_2) 
    select id, col_1, col_2 
    from staging_table 
    where not exists (select * 
         from target_table 
         where target_table.id = staging_table.id) 
    returning staging_table.id; 
) 
delete from staging_table 
where id in (select id from inserted); 

A(非唯一的)指標應該幫助的性能。

+0

謝謝,看起來不錯。這種方式有多快?慢得多,只是批量直接插入目標表? –