[英]Deleting records from Oracle 11g with JDBC
我需要從包含900萬條記錄的表中刪除10000條記錄。 將從復雜查詢中獲取要刪除的ID,並將其存儲在Java集合中。
我有3種方法來實現這一點
1)創建一個准備好的語句,並將10000條語句添加到批處理中並執行它。
聲明將如下所示
Delete from <table_name> where id=?;
2)寫一個“ in”查詢,而不是批量使用“ =”。 喜歡
在這種情況下,可以在Java代碼中以逗號分隔的值創建10000個ID,並將其添加到查詢中。 或者,將10000個ID插入到臨時表中,並在子查詢中從該表中進行選擇。
Delete from <table_name> where id in (<CSV>);
or
Delete from <table_name> where id in (select id from <temp_table>);
表中沒有約束和索引。 而且我無法添加一個,因為我正在處理現有表。
第一個選擇是花很多時間才能完成。 它已運行15小時,但仍未完成。
您的第一個版本限制為1000個值,並且效果通常不佳。 第二種方法可能會更好,但是您必須有一個全局臨時表,並填充它是一個額外的步驟。
您可以將Java集合轉換為Oracle集合。 您可以為此創建自己的表類型,但是可以在其中使用諸如ODCINUMBERLIST之類的內置表類型。 您可以將其視為表集合表達式。
具體細節可能會有所不同,具體取決於您的Java集合類型,但是大綱如下所示:
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST",
conn);
oracle.sql.ARRAY oraIDs = new oracle.sql.ARRAY(aDesc, conn, yourJavaCollectinOfIDs);
cStmt = (OracleCallableStatement) conn.prepareCall(
"Delete from <table_name>
where id in (select column_value from table(?))");
cStmt.setArray(1, oraIDs);
cStmt.execute();
除非它已經不是一個簡單的數組,否則您將需要在調用中將Java集合轉換為數組; 例如,如果您使用的是名為yourArrayList的ArrayList,則可以執行以下操作:
oracle.sql.ARRAY oraIDs = new oracle.sql.ARRAY(aDesc, conn, yourArrayList.toArray());
您仍然會遭受缺少主鍵或索引的困擾,但是與CSV列表(或多個CSV列表或在一起,因為您擁有1000多個ID在一起)相比,它為Oracle提供了更好的優化機會。
您不應該通過從Java代碼執行10000條語句來使用第一個選項。
創建一個臨時表是一個好主意。 但是大多數情況下,您的IN (...)
子句不能包含超過1000個項目。 因此,您使用CSV
的方法可能不會成功。
你可以去
Delete from <table_name> where id in (select id from <temp_table>);
但是這種方法也沒有優化。 最好將您的delete
語句更改為:
Delete from <table_name> m where exists (select id from <temp_table> t where m.id = t.id);
但是,如果您經常執行此類操作,則強烈建議為您<table_name>
甚至您的<temp_table>
添加一些約束和索引。 它將像魅力一樣增加您的操作執行時間。
WHERE ... IN(...)是必經之路。
IN子句可以引用您已填充的臨時表(您的原始想法),也可以包含任何選定的(固定的)數量? 參數。 它將使db往返次數減少等於選擇的次數的因數,但不一定等於1。 遍歷您的集合並分塊處理它。
嘗試這樣。
Delete from <table_name> where
id in (1, 2, 3, ... ,1000)
or id in (1001, 1002, ... , 2000)
....
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.