ツリーを表す履歴推移閉包表があります。
create table TRANSITIVE_CLOSURE
(
CHILD_NODE_ID number not null enable,
ANCESTOR_NODE_ID number not null enable,
DISTANCE number not null enable,
FROM_DATE date not null enable,
TO_DATE date not null enable,
constraint TRANSITIVE_CLOSURE_PK unique (CHILD_NODE_ID, ANCESTOR_NODE_ID, DISTANCE, FROM_DATE, TO_DATE)
);
サンプルデータは次のとおりです。
CHILD_NODE_ID | ANCESTOR_NODE_ID | DISTANCE
--------------------------------------------
1 | 1 | 0
2 | 1 | 1
2 | 2 | 0
3 | 1 | 2
3 | 2 | 1
3 | 3 | 0
残念ながら、ルート ノードを見つけるための現在のクエリでは、完全なテーブル スキャンが発生します。
select *
from transitive_closure tc
where
distance = 0
and not exists (
select null
from transitive_closure tci
where tc.child_node_id = tci.child_node_id
and tci.distance <> 0
);
表面的にはそれほど高価には見えませんが、100 万行に近づくにつれて、この特定のクエリは厄介になり始めています... 特に、レガシー サポートのために隣接ツリーを取得するビューの一部である場合はそうです。
推移閉包のルート ノードを見つけるより良い方法はありますか? 古いレガシ コードをすべて書き直したいのですが、できません...そのため、何らかの方法で隣接リストを作成する必要があります。ルート ノード以外のすべてを取得するのは簡単ですが、より良い方法はありますか? 私はこの問題について間違った方法で考えていますか?
80 万行のテーブルに対するクエリ プラン。
OPERATION OBJECT_NAME OPTIONS COST
SELECT STATEMENT 2301
HASH JOIN RIGHT ANTI 2301
Access Predicates
TC.CHILD_NODE_ID=TCI.CHILD_NODE_ID
TABLE ACCESS TRANSITIVE_CLOSURE FULL 961
Filter Predicates
TCI.DISTANCE = 1
TABLE ACCESS TRANSITIVE_CLOSURE FULL 962
Filter Predicates
DISTANCE=0