2012-11-01 2 views
3

다음 (단순화 된) CTE를 실험했습니다. 테이블 변수()를 사용하면 쿼리가 취소되기 전에 몇 분 동안 쿼리가 실행됩니다. 다른 주석 처리 된 메소드는 모두 1 초 이내에 반환됩니다.공통 테이블 테이블 변수를 사용할 때 표현식이 느립니다.

전체 WHERE 절을 INNER JOIN으로 바꾸면 빠릅니다.

테이블 변수를 사용하는 것이 왜 그렇게 천천히 실행됩니까?

FWIW : 데이터베이스에 250 만 개의 레코드가 있고 내부 쿼리가 2 개의 레코드를 반환합니다.

CREATE TABLE #rootTempTable (RootID int PRIMARY KEY) 
INSERT INTO #rootTempTable VALUES (1360); 

DECLARE @rootTableVar TABLE (RootID int PRIMARY KEY); 
INSERT INTO @rootTableVar VALUES (1360); 

WITH My_CTE AS 
(
     SELECT ROW_NUMBER() OVER(ORDER BY d.DocumentID) rownum, d.DocumentID, d.Title 
     FROM [Document] d 
     WHERE d.LocationID IN 
     (
       SELECT LocationID 
       FROM Location 
        JOIN @rootTableVar rtv ON Location.RootID = rtv.RootID -- VERY SLOW! 
        --JOIN #rootTempTable tt ON Location.RootID = tt.RootID -- Fast 
        --JOIN (SELECT 1360 as RootID) AS rt ON Location.RootID = rt.RootID -- Fast 
        --WHERE RootID = 1360 -- Fast 
     )   
) 
SELECT * FROM My_CTE WHERE (rownum > 0) AND (rownum <= 100) ORDER BY rownum 

이것은 테이블 변수를 사용할 때입니다. https://docs.google.com/open?id=0B66I-fxlyEtEZEthV3ZaWlNLWXM

테이블 변수 : https://docs.google.com/open?id=0B66I-fxlyEtEbUFZa3RJejFCTkk

+0

테이블 변수 및 임시 테이블 버전에 대한 쿼리 계획을 게시하십시오. – RBarryYoung

+0

이것은 실제로 테이블 변수 내에서 기본 키를 본 처음입니다. 나는 궁금하다. 실행 계획은 무엇을 말해야 하는가? –

+0

테이블 변수 버전이 완료 될 때까지 보자 : 17m 41s. 실행 계획에 대해 원하는 특정 형식? BTW - 기본 키는 제가 차이를 만들 것인지 여부를 확인하기 위해 함께 놀고 있었던 것입니다. 그것은 보이지 않았다. –

답변

4

무엇 쿼리 계획을 명확하게하는 것입니다 임시 테이블이

XML 형식으로 enter image description here

실행 계획을 : 쿼리 실행 17분 점령 테이블 변수 버전은 악명 높은 "테이블 변수 카디널리티 추정"문제로 고통 받고 있습니다. 이것은 주로 임시 테이블과 달리 테이블 변수가 통계를 지원하지 않기 때문에 발생합니다. 폴 화이트 (Paul White)가 작성한이 기사에서는이 내용을 매우 자세히 설명합니다 : http://sqlblog.com/blogs/paul_white/archive/2012/08/15/temporary-tables-in-stored-procedures.aspx.

가장 간단한 해결 방법은 쿼리의 끝에 OPTION (Recompile); 절을 추가하는 것입니다. 이 방법은 이전 버전의 SQL Server에서는 작동하지 않지만 이후 버전에서는 더 나은 카디널리티 예상치를 가져와 임시 테이블 버전과 동일한 쿼리 계획을 생성해야합니다.

가능하지 않은 다른 해결책이 있으므로 알려주세요.

+0

감사합니다. 좋은 제안입니다. 그러나 그것은 내가 CTE 내에서가 아니라 외부 SELECT 후에 추가 할 수있는 것처럼 보이며 많은 차이를 만드는 것처럼 보입니다. 결국 나는 다소 도움이되는 인덱스를 재구성/재구성했으며, CTE를 사용하지 않는 대체 쿼리도 검토하고 있습니다. –

0

부분 솔루션 : 인덱스 실제 통계 보고서를 사용하여 SQL Server에서 권장하는대로 테이블의 인덱스를 다시 작성하거나 재구성하는 것이 많은 도움을주었습니다. 이 보고서는 데이터베이스> 보고서> 표준 보고서> 색인 실제 통계를 마우스 오른쪽 단추로 클릭하면 사용할 수 있습니다.