2012-04-10 10 views
2

Oracle 11gデータベースでは、プライマリ・キーI_Node(int)とI_Parent_Node(int)という別のレコードを参照する表があります。同じテーブルにルートノードにはI_Parent_Node = nullがあります。このようにして、ノード、リーフ、ブランチのツリー構造を形成します。自己参照表のOracleでの削除時間を改善する方法

ノードのブランチ全体を一度に削除する必要があります。ノードとそのすべての子を意味します。時には、これは多くの、多くのレコード、例えば50,000以上です。カスケード削除は自己参照テーブルでは許可されていないため、葉で始まり、ツリーをバックアップするために1つずつ削除する必要があります。私たちは何時間もの削除時間を経験しました。

オフピーク時に別のプログラムで削除マークされたノードをクリーンアウトする「削除用のマーキング」手法を検討していますが、データベース設計の変更など、ここで助けてください。私は仕事で学んだことを除いてOracleに訓練されておらず、データベースを作成した人々はそのような大量を念頭に置いていませんでした。私はまだ固定設計ではないので、データベース設計の変更を公開しています。

+1

"カスケード削除は自己参照表では許可されていません"という意味ですか? 'create table test1(I_Node番号主キー、I_Parent_Node番号、制約test1_fk外部キー(I_Parent_Node)はdeleteカスケードでtest1(I_Node)を参照します); ' –

答えて

1

メインテーブルから階層構造を分離することを検討してください。したがって、メインテーブルにはプライマリID(「ID」と呼ぶ)があり、階層テーブルには「ID、ParentID、TreeID」があります。 ParentIDはそのIDの親ノードであり、TreeIDはツリー(レベル1)の中で最も高い親です。

したがって、レベル1のノードは次のようになり:

ID, ParentID, TreeID 
3, 2, 1 
:レベル3のノードは次のようになり

ID, ParentID, TreeID 
2, 1, 1 

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

レベル2ノードは次のようになり

など。

Oracle hierarchy queries(クエリで接続)を使用してツリーをクエリまたはトラバースします。このテーブルは非常に細く(これらの3 +いくつかの変更された日付かもしれない)、非常に薄いので、これらの関係を更新する方がはるかに高速で、メインテーブルを揺らすよりもスケールが良くなるはずです。

+0

ありがとう、私はこれを見て、それはうまくいく! –

1

遅延可能制約と階層クエリでこれを実行できるはずです。

(I_Parent_Nodeの)外部キー制約がまだ延期されていない場合は、削除してキーワード "DEFERRABLE"で再作成してください。そうでない場合は、あなたの外部キーを再作成し

ドロップ&:

はここでOracleの例からEMPLOYEES表を使用した例です(私はこれが実行さなるように、あまりにも、それは実際にも例のために必要ではないですDEPARTMENTSテーブルを修正しました) 、あなたの取引で

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; 

あなたのcontraintsを延期し、階層的なクエリを使用して削除:現在、繰延

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

+1

あなた自身の投稿を編集して、忘れたものを追加することができます。一番下にある編集ボタンをクリックして、変更が[有意義]であることを確認してください(http://stackoverflow.com/privileges/edit)。 – Ben

0

標準的なチューニングを済ませたとします。ノードと親ノードのID列は適切なインデックスに登録されていますか?

(1)この問題へのアプローチの1つは、PL/SQLを使用することです。最初にリーフ・ローを戻す階層問合せを使用して、削除するIDをバルク収集します。配列を使用して一括削除(FORALL)します。

(2)もう1つのアプローチは、ソフト削除です - 行を「削除済み」としてマークしますが、実際には削除しないでください。アプリケーションを変更する(またはOracle VPDを使用して、問合せから「削除された」行を自動的に省略する)必要があります。これは、ノードの削除が比較的まれである場合には、うまくいく可能性があります。多くのノードを定期的に削除している場合は、古いデータがたくさんあるため、テーブルが乱雑になります。