階層リンク(parent_id、child_id)のグラフを表すテーブルがあります テーブルには親、子、両方のインデックスがあります。 グラフにはループが含まれている可能性があります。グラフを確認する必要があります(または、ループをすべて削除する必要があります)。postgresqlは再帰的クエリのインデックスを無視します
そして、私はノードのすべての親を再帰的にクエリする必要があります。このクエリはpostgresの場合
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
非常に素晴らしい計画を使用する予定です:
"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