У меня есть историческая транзитивная таблица замыканий, которая представляет дерево.
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
);
На первый взгляд, это не выглядит слишком дорого, но когда я подхожу к миллиону строк, этот конкретный запрос начинает становиться неприятным ... особенно, когда он является частью представления, которое захватывает дерево смежности для поддержки прежних версий.
Есть ли лучший способ найти корневой узел транзитивного замыкания? Я хотел бы переписать весь наш старый унаследованный код, но я не могу ... поэтому мне нужно как-то составить список смежности. Получить все, кроме корневого узла, легко, так есть ли лучший способ? Думаю ли я об этой проблеме неправильно?
План запроса для таблицы с 800 тыс. Строк.
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