2014-09-28 1 views
0

: 다음 쿼리와외부 WHERE 절이 재귀 CTE에서 최적화되어 있습니까? 다음 테이블 정의와

CREATE TABLE Nodes(id INTEGER, child INTEGER); 

INSERT INTO Nodes(id, child) VALUES(1, 10); 
INSERT INTO Nodes(id, child) VALUES(1, 11); 
INSERT INTO Nodes(id, child) VALUES(1, 12); 

INSERT INTO Nodes(id, child) VALUES(10, 100); 
INSERT INTO Nodes(id, child) VALUES(10, 101); 
INSERT INTO Nodes(id, child) VALUES(10, 102); 

INSERT INTO Nodes(id, child) VALUES(2, 20); 
INSERT INTO Nodes(id, child) VALUES(2, 21); 
INSERT INTO Nodes(id, child) VALUES(2, 22); 

INSERT INTO Nodes(id, child) VALUES(20, 200); 
INSERT INTO Nodes(id, child) VALUES(20, 201); 
INSERT INTO Nodes(id, child) VALUES(20, 202); 

:

WITH RECURSIVE members(base, id, level) AS ( 
    SELECT n1.id, n1.id, 0 
    FROM Nodes n1 
    LEFT OUTER JOIN Nodes n2 ON n2.child = n1.id 
    WHERE n2.id IS NULL 

    UNION 

    SELECT m.base, n.child, m.level + 1 
    FROM members m 
    INNER JOIN Nodes n ON m.id=n.id 
) 
SELECT m.id, m.level 
FROM members m 
WHERE m.base IN (1) 

절은 재귀 CTE에 최적화 된 외부인가? 내가 사용한 것으로 생각되는 대체물은 다음과 같습니다 :

WITH RECURSIVE members(id, level) AS ( 
    VALUES (1, 0) 

    UNION 

    SELECT n.child, m.level + 1 
    FROM members m 
    INNER JOIN Nodes n ON m.id=n.id 
) 
SELECT m.id, m.level 
FROM members m 

그러나보기 밖으로 만들 수 없다는 문제가 있습니다. 따라서 둘 사이의 성능 차이가 최소한이라면 재귀 적 CTE에서 뷰를 만든 다음 쿼리 만하는 것이 좋습니다.

+0

그 나머지 부분은 VALUES 문입니다. 두 가지 요소가 있어야합니다. –

+0

@PieterGeerkens 예, 각 ID마다 반복적으로'(_ID_, 0) '으로 채워집니다. 따라서 두 번째 쿼리는 루트 노드 ID 만 전달되고 자체 검사는 수행하지 않는다고 가정합니다. – chacham15

+0

오! 나는'% s'이 엔진에 의해'무엇이 필요한지, 당연히 정확하게 '해석 된 마법의 문자열이라는 것을 깨닫지 못했습니다. –

답변

1

하면 CTE 내부 쿼리에 WHERE 절을 적용 할 수 있으려면, 데이터베이스는 첫 번째 열의

  • 모든 값은 재귀에 의해 변경되지 않습니다 것을 증명하고 다시 이동해야 할 것 기본 쿼리 및 일반적으로 해당 결과가
  • 인 경우 필터링 된 행에는 쿼리 결과에 나타날 수있는 자식이 없거나 다른 방법으로 CTE에 영향을 줄 수 있습니다.

이러한 증명 기가 존재하지 않습니다. Subquery flattening의 제한 22를 참조하십시오.

0

첫 번째 쿼리가 최적이 아닌 이유를 보려면 UNION 대신 UNION ALL을 둘 다 실행 해보십시오. 샘플 데이터가 주어지면 첫 번째 행은 21 행을 반환하고 두 번째 행은 7을 반환합니다.

정렬 및 중복 제거를 수행하면 실제 첫 번째 쿼리의 중복 행이 제거됩니다.이 단계는 필요하지 않습니다. 실제 두 번째 쿼리