我有一张表表示层次结构链接图(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