我有一個Oracle表格表示父子關係,並且我想提高查找祖先記錄的層次結構的查詢性能。我與小數據集在這裏測試,但真正的桌子大得多:具有分層關係的SQL查詢中的性能問題
id name parent_id tagged
== ==== ========= ======
1 One null null
2 Two 1 1
3 Three 2 null
4 Four 3 null
5 Five null null
6 Six 5 1
7 Seven 6 null
8 Eight null null
9 Nine 8 null
PARENT_ID指回id在同一個表的外鍵關係。
我想編寫一個查詢,它返回每個葉子記錄(那些沒有後代的記錄...在這個例子中是id 4和id 7),它有一個祖先記錄tagged = 1
(通過parent_id關係回溯) 。
因此,對於上面的源數據,我想我的查詢返回:
id name tagged_ancestor_id
== ==== ==================
4 Four 2
7 Seven 6
我目前的查詢檢索這些記錄是:
select * from (
select id,
name,
connect_by_root id tagged_ancestor_id
from mytree
connect by prior id = parent_id
start with tagged is not null
) m1
where not exists (
select * from mytree m2 where m2.parent_id = m1.id
)
此查詢工作正常在這個簡單的小例如表格,但是在我的真實表格上它的表現非常糟糕,它有大約1100萬條記錄。查詢需要一分鐘才能運行。
connect by
子句中的兩個字段都有索引。start with
子句中的「tagged」字段也有一個索引,我的表中有大約1,500,000條記錄,在這個字段中有非空值。where
子句似乎不是問題,因爲修改它以使用where name = 'somename'
而不是where not exists ...
返回特定名稱(也是索引的)時,查詢仍然需要大約相同的時間量。
那麼,我可以使用什麼策略來嘗試使這些層次結構上的查詢運行得更快?
如果您可以修改模式,則可以重新構建它以存儲修改的預定義樹遍歷,但是需要添加2個附加列(左側和右側值)。幾年前,我在一個我現在無法找到的教程中成功完成了這個任務。 (你應該得到一些額外的性能,但需要花費空間 – ozborn
我確實可以控制模式,因此如果增加一些列是最好的方法來改善這種性能,那麼就可以了。我想我可以把一個標記爲祖先在自己的領域,並做到這一點,但似乎這個查詢可以做得更快。 –
這裏是適當的維基百科參考:https://en.wikipedia.org/wiki/Nested_set_model我不知道我明白在其自己的領域藏匿一個標記的祖先會幫助你(除非你存儲所有這些?),但我可能不理解你的問題...? – ozborn