2012-04-10 47 views
2

在我們的Oracle 11g數據庫中,我們有一個表,其中有一個主鍵I_Node(int),還有一個名爲I_Parent_Node(int)的列,該列引用了另一條記錄在同一張桌子裏。根節點具有I_Parent_Node = null。通過這種方式,我們可以形成節點,樹葉,樹枝的樹狀結構,無論您想要調用它們。如何提高Oracle在自引用表中的刪除時間

我們經常需要一次刪除整個節點分支,即節點及其所有子節點。有時這是很多很多的記錄,比如說5萬或更多。由於級聯刪除不允許在自引用表上進行,因此我們不得不逐個從樹葉開始刪除並重新進行樹的備份。我們經歷了長達數小時的刪除時間。

我們正在考慮做一個「刪除標記」技術,其中一個單獨的程序將在非高峯時間清理標記爲刪除的節點,但我對數據庫設計更改或其他某種Oracle構造是否可以在這裏幫忙。除了我在工作中學到的知識外,我還沒有接受過Oracle的培訓,而創建數據庫的人並沒有如此大的數量。由於它還不是一個固定的設計,因此我願意接受數據庫設計更改。

+1

你是什麼意思,「在自引用表上不允許級聯刪除」?似乎工作對我來說沒問題:'create table test1(I_Node number primary key,I_Parent_Node number,constraint test1_fk foreign key(I_Parent_Node)references test1(I_Node)on delete cascade);' – 2012-04-11 03:56:49

回答

1

您可能想要考慮從主表中分離層次結構。所以你的主表只會有主要的ID(讓我們稱之爲「ID」),而你的層次結構表將具有「ID,ParentID,TreeID」。 ParentID是該ID的父節點,而TreeID是樹中最高的父級(級別1)。

因此,一個電平1節點將如下所示:

ID, ParentID, TreeID 
1, [null], 1 

A級2節點將如下所示:

ID, ParentID, TreeID 
2, 1, 1 

A級3節點將如下所示:

ID, ParentID, TreeID 
3, 2, 1 

等。

您將使用Oracle hierarchy queries(通過查詢連接)來查詢或遍歷樹。這個表格將非常細小(不是很多列,這些3 +一些修改的日期可能),所以更新這些關係應該快得多,並且比調整主表更好。

+0

謝謝,我會看看這個,稍後回覆if它解決了! – 2012-04-12 19:56:19

1

您應該可以使用可延期約束和分層查詢來做到這一點。

如果您的外鍵約束(在I_Parent_Node上)尚未推遲,請將其刪除並使用關鍵字「DEFERRABLE」重新創建它。

下面是一個使用EMPLOYEES表從Oracle的實例的實例(我修改部門表也因此,這將執行,這真的是不需要的例子雖然):

降&重新創建外鍵,如果它不目前推遲的:

alter table employees drop constraint emp_manager_fk; 
alter table employees add constraint emp_manager_fk foreign key (manager_id) references employees(employee_id) deferrable; 

在您的交易,推遲你的約束上,使用分層查詢刪除:

set constraints all deferred; 

delete 
from  employees e 
where employee_id in (select employee_id 
         from  employees 
         start with employee_id = 108 
         connect by prior employee_id = manager_id); 

「108」是我的「父」記錄的ID。

+0

我忘了添加,爲了提升性能,employee_id和manager_id都應該被索引(你的I_Node和I_Parent_Node列);如果不是,子查詢可能是一個相當的瓶頸。 – krissco 2012-04-10 21:06:28

+1

您可以編輯自己的帖子以添加您忘記的任何內容。只需點擊底部的編輯按鈕,並確保更改是[有意義的](http://stackoverflow.com/privileges/edit)。 – Ben 2012-04-10 21:29:02

0

我假設你已經完成了標準調整 - 即是適合索引的節點和父節點ID列嗎?

(1)解決此問題的一種方法是使用PL/SQL。使用首先返回葉子行的分層查詢批量收集要刪除的ID到數組中;然後使用該數組進行批量刪除(FORALL)。 (2)另一種方法是軟刪除 - 將行標記爲「已刪除」,但從不實際刪除它們。您需要修改應用程序(或使用Oracle VPD自動忽略查詢中的「已刪除」行)。如果刪除節點相對較少,這可能工作得相當好;但是如果你經常刪除大量的節點,那麼這會使表格中包含大量的舊數據。

相關問題