I have a historical transitive closure table that represents a tree.
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) );
Here are some sample data:
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
Unfortunately, my current query to search for the root of the node causes a full table scan:
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 );
At first glance, this does not look too expensive, but as you approach 1 million rows, this particular query starts to become unpleasant ... especially when it is part of a view that spans the adjacency tree for old support.
Is there a better way to find the root node of a transitive closure? I would like to rewrite all of our old code for legacy code, but I can't ... so I need to somehow create an adjacency list. Getting everything except the root node is easy, so is there a better way? Am I thinking about this problem wrong?
Query plan for a table with 800k rows.
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