編輯:請回答我問的兩個答案之一。我知道還有其他的選擇,在另一種情況下會更好。這些其他潛在的選項(分區表,作爲一個大批量刪除語句不分批提交等)是不是選項在我的情況下,由於我的控制之外的事情。SQL優化問題(oracle)
我有幾個非常大的表格要刪除。所有的索引都有相同的外鍵。我需要刪除所有表中的某些記錄。
table source
id --primary_key
import_source --used for choosing the ids to delete
table t1
id --foreign key
--other fields
table t2
id --foreign key
--different other fields
通常做了刪除這樣的時候,我把一個循環來通過所有的ID:
declare
my_counter integer := 0;
begin
for cur in (
select id from source where import_source = 'bad.txt'
) loop
begin
delete from source where id = cur.id;
delete from t1 where id = cur.id;
delete from t2 where id = cur.id;
my_counter := my_counter + 1;
if my_counter > 500 then
my_counter := 0;
commit;
end if;
end;
end loop;
commit;
end;
然而,在一些代碼,我看到了其他地方,它被放在一起單獨的循環,每個刪除一個。
declare
type import_ids is table of integer index by pls_integer;
my_count integer := 0;
begin
select id bulk collect into my_import_ids from source where import_source = 'bad.txt'
for h in 1..my_import_ids.count
delete from t1 where id = my_import_ids(h);
--do commit check
end loop;
for h in 1..my_import_ids.count
delete from t2 where id = my_import_ids(h);
--do commit check
end loop;
--do commit check will be replaced with the same chunk to commit every 500 rows as the above query
所以我需要以下回答之一:
1)哪一個是更好?
2)如何找出哪個更適合我的特殊情況? (也就是說,如果這取決於我有多少表,他們是多麼大等)
編輯:
我必須這樣做在一個循環中,由於這些表的大小。我將從具有數億條記錄的表中刪除數千條記錄。這發生在一個無法承受這麼長時間表鎖定的系統上。
編輯:
注:我需要分批提交。數據量太大,無法在一批中完成。回滾表將使我們的數據庫崩潰。
如果有一種方法可以批量提交而不是循環,我願意聽到它。否則,不要打擾說我不應該使用循環...
如果您覺得由於表的大尺寸而必須使用循環,那麼您(和/或DBA)是否使用數據庫引擎的分區功能來查看?這是分區幫助的「用例」之一。例如,如果您擁有10 TB的10 TB行表,那麼刪除分區(基於ID)比遍歷數百萬行更容易。 – JasDev 2009-12-03 17:43:01
是的,我們已經考慮過這個。我們已經分割了我們的數據庫。但是,t1和t2(etc)表可以通過幾種不同的方式訪問(基於id以外的字段)。因此,任何對它們的分割都會傷害整體。 我遺漏了很多不影響我的問題的細節,但確實意味着我們無法對t1,t2等進行分區。 – 2009-12-03 18:00:00
您知道無論刪除多少行,您都不會鎖好桌子吧?如果您正在刪除某個其他進程嘗試更新的行,則只會出現鎖爭用,這似乎不太可能。如果有人試圖更新您嘗試刪除的行,那麼阻止該行顯得非常合理。 – 2009-12-04 06:01:23