것 포인트까지 최적화 된 것으로 나타났습니다.
다양한 하위 쿼리가 예상대로 재사용되고 개별적으로 최적화되며 Postgres는 다른 쿼리와 마찬가지로 후자를 최적화합니다.
필자의 주요 불만은 가능한 경우 CTE에 제약 조건을 주입하지 않는다는 것과 관계가 있습니다. 예를 들어
:
이
with recursive
parents as (
select node.id,
node.parent_id
from nodes as node
union all
select node.id,
parent.parent_id
from parents as node
join nodes as parent on parent.id = node.parent_id
)
select parent_id
from parents
where id = 2;
포스트 그레스가 이상적으로 이해하는 것, 위의, 그게 할 수있는 ( 같이 node.id 이후 을 반환) :
with recursive
parents as (
select node.id,
node.parent_id
from nodes as node
where id = 2
union all
select node.id,
parent.parent_id
from parents as node
join nodes as parent on parent.id = node.parent_id
)
select parent_id
from parents;
을 ... 기본 키에서 색인 스캔을 사용하십시오. 실제로 실제로 CTE가 지시하면 정확하게 수행 할 것입니다. 모든 행에 대해 모든 부모를 반복적으로 가져오고, 필요한 경우 이름이 지정되지 않은 임시 테이블에 결과 세트를 놓은 다음 결과 세트에서 각 행을 확인하십시오. id = 2.
즉, CTE는 돌아 오는 "원본"테이블/행/열 집합의 추적을 유지하지 않습니다. 이것이 최적화 될 때까지 재귀 쿼리에 대한 뷰를 생성하는 것은 최선의 방법입니다.
create function parents(id int) as returns table (id int) $$
with recursive
parents as (
select node.id,
node.parent_id
from nodes as node
where id = $1
union all
select node.id,
parent.parent_id
from parents as node
join nodes as parent on parent.id = node.parent_id
)
select parent_id
from parents;
$$ language sql stable strict rows 5 cost 1;
또 다른 문제는 (사실, 매우 같은 이유로) 재귀 CTE를 가진 FOR UPDATE를 사용할 수있다 :
한편의 좋은 해결 방법은 대신 SQL 함수를 만드는 것입니다.
언어 수준에서'WITH RECURSIVE '를 사용하는 모든 이유는 데이터베이스가 사용자가하려는 일을 알고 사용자의 의도에 따라 행동 할 수 있도록하기 위해서입니다. –
@mu 네, 저도 그렇게 생각합니다. 그러나 데이터베이스 레벨에서 인덱스 등을 사용하여 어떻게 최적화 할 수 있는지는 분명하지 않습니다. 일부 작업은 일반적으로 어렵습니다. 제안이 끝나면 내가 마자 내 결과를 게시 할 것입니다. – julkiewicz
@julkiewicz 전이 클로저 테이블은 사실 이러한 쿼리에 대한 인덱스입니다. 비슷한 기술을 사용하는 색인 유형을 제공 할 수없는 이유는 없습니다. – EricS