我有一張表表示層次結構鏈接圖(parent_id,child_id) 該表具有父,子和兩者的索引。 該圖可能包含循環,我需要檢查它們(或者,也許我需要找到所有循環來消除它們)。postgresql忽略遞歸查詢的索引
而我需要查詢一個節點的所有父母recustively。 爲此,我使用此查詢(它應該考慮到保存):
WITH RECURSIVE recursion(parent_id, child_id, node_id, path) AS (
SELECT h.parent_id,
h.child_id,
h.child_id AS node_id,
ARRAY[h.parent_id, h.child_id] AS path
FROM hierarchy h
UNION ALL
SELECT h.parent_id,
h.child_id,
r.node_id,
ARRAY[h.parent_id] || r.path
FROM hierarchy h JOIN recursion r ON h.child_id = r.parent_id
WHERE NOT r.path @> ARRAY[h.parent_id]
)
SELECT parent_id,
child_id,
node_id,
path
FROM recursion
where node_id = 883
對於此查詢的Postgres將使用非常了不起的計劃:
"CTE Scan on recursion (cost=2703799682.88..4162807558.70 rows=324223972 width=56)"
" Filter: (node_id = 883)"
" CTE recursion"
" -> Recursive Union (cost=0.00..2703799682.88 rows=64844794481 width=56)"
" -> Seq Scan on hierarchy h (cost=0.00..74728.61 rows=4210061 width=56)"
" -> Merge Join (cost=10058756.99..140682906.47 rows=6484058442 width=56)"
" Merge Cond: (h_1.child_id = r.parent_id)"
" Join Filter: (NOT (r.path @> ARRAY[h_1.parent_id]))"
" -> Index Scan using hierarchy_idx_child on hierarchy h_1 (cost=0.43..256998.25 rows=4210061 width=16)"
" -> Materialize (cost=10058756.56..10269259.61 rows=42100610 width=48)"
" -> Sort (cost=10058756.56..10164008.08 rows=42100610 width=48)"
" Sort Key: r.parent_id"
" -> WorkTable Scan on recursion r (cost=0.00..842012.20 rows=42100610 width=48)"
好像Postgres沒有理解node_id上的外部過濾器應用於第一個遞歸子查詢中的child_id。
我想我做錯了很多事情。但究竟在哪裏?
通常情況下,在UNION的第一部分的條件:要麼頂級節點(沒有父)或葉節點(沒有孩子),或某些特定記錄#你有興趣在您的代碼使用。 *每個*記錄作爲連鎖起動器。 – wildplasser
聯合的第一個查詢檢索表的所有**行。沒有指標將有助於與 –
我希望能Postgres的內部子查詢合併外部過濾器。看起來我太樂觀了。 – qMax