2011-09-06 65 views
4

我有一個postgresql數據庫與約150表(這是一個Django 1.2項目)。 Django在創建表時將ON DELETE NO ACTIONON UPDATE NO ACTION添加到外鍵。Django 1.2 PostgreSQL級聯刪除鍵與ON DELETE NO ACTION

現在我需要批量從一堆基於某些條件表的刪除數據(約80萬條記錄)。

使用Model.objects.filter().delete()不是一個選項,因爲數據是巨大的,它需要大量的時間。

只有sanest選項似乎級聯刪除,但由於Django的有添加「ON DELETE NO ACTION」它看起來像一個沒有選擇。

所以我的問題:有沒有辦法改變這一切foreing鍵在一個簡單的方法DELETE CASCADE(其中還有不少的),或者類似的東西。

(我知道我可以手動編寫每個表的SQL查詢,但是這將是一個巨大且難以維護的任務。)

回答

1

由於其中包含的鏈接中指出安德魯的回答是,如果你在Django中設置爲CASCADE,那麼Django會去刪除「零售」。如果它設置爲NO ACTION,則可以創建數據庫級外鍵定義來處理事情。這聽起來像是一個合理的計劃。

確保您有一個在上定義的索引,它爲每個外鍵引用列;否則你會看到非常慢的表現。一些數據庫產品會在您定義外鍵時自動創建這樣的索引,但是在某些情況下這並不是有利的,所以PostgreSQL會將這些事情放在您的手中,以根據您的需要進行優化。 (就像一個例子,它可能不值得在正常操作期間維護索引的成本,但值得在清除之前將其構建並丟棄它。)

0

一個註釋:ON DELETE CASCADE在批量操作。原因是這是作爲觸發器完成的。因此它看起來從算法的角度來看,方法是:

for row in delete_set: 
    for dependent row in (scan for referencing rows): 
     delete dependent row 

如果要刪除這個轉化父表中的80萬行成的從屬表800000次單獨刪除掃描。即使在最好的情況下,索引可用800000單獨索引掃描也會比一個順序掃描慢得多。

一種更好的方式做,這是在9.1或更高版本才能使用可寫公用表表達式,或者只是做在同一個事務獨立delete語句。喜歡的東西:

WITH rows_to_delete (id) AS (
    SELECT id FROM mytable WHERE where_condition 
), 
deleted_rows (id) AS (
    DELETE FROM referencing_table WHERE mytable_id IN (select id FROM rows_to_delete) 
    RETURNING mytable_id 
), 
DELETE FROM mytable WHERE id IN (select id FROM deleted_rows); 

這減少了一些像算法:

掃描的行刪除作爲delete_set 的依賴性掃描依賴於刪除行: 刪除依賴 爲to_delete在掃描的行通過刪除家屬引用: 刪除to_delete

擺脫強制嵌套循環掃描將大大加快速度。