결합 술어에서 변수를 참조하는 것이 중첩 루프를 강제하는 이유는 무엇입니까?


16

최근 에이 문제를 발견했으며 온라인에서 토론을 찾을 수 없습니다.

아래 쿼리

DECLARE @S VARCHAR(1) = '';

WITH T
     AS (SELECT name + @S AS name2,
                *
         FROM   master..spt_values)
SELECT *
FROM   T T1
       INNER JOIN T T2
         ON T1.name2 = T2.name2;

항상 중첩 루프 계획을 얻습니다.

여기에 이미지 설명을 입력하십시오

문제 INNER HASH JOIN또는 INNER MERGE JOIN힌트 를 강제로 적용하려고 하면 다음 오류가 발생합니다.

이 쿼리에 정의 된 힌트로 인해 쿼리 프로세서가 쿼리 계획을 생성 할 수 없습니다. 힌트를 지정하지 않고 SET FORCEPLAN을 사용하지 않고 쿼리를 다시 제출하십시오.

변수를 집계로 래핑하여 해시 또는 병합 조인을 사용할 수있는 해결 방법을 찾았습니다. 생성 된 계획은 훨씬 저렴합니다 (19.2025 vs 0.261987).

DECLARE @S2 VARCHAR(1) = '';

WITH T
     AS (SELECT name + (SELECT MAX(@S2)) AS name2,
                *
         FROM   spt_values)
SELECT *
FROM   T T1
       INNER JOIN T T2
         ON T1.name2 = T2.name2; 

여기에 이미지 설명을 입력하십시오

이 행동의 이유는 무엇입니까? 내가 찾은 것보다 더 나은 해결 방법이 있습니까? (아마도 추가 실행 계획 분기가 필요하지 않음)

답변:


13

SQL 2012 인스턴스에서 쿼리를 시도했지만 추적 플래그 4199가 문제를 해결하는 것으로 보입니다. 이 기능을 사용하면 총 비용이 0.24이고 추가 브랜치가없는 병합 조인을 얻습니다.

이 문제에 대한 특정 기술 자료 문서는 쿼리의 조인 조건 자에 SQL Server 2005 또는 SQL Server 2008의 외부 참조 열이있을 때 성능 문제가 발생한다는 것입니다.

여기에 이미지 설명을 입력하십시오

더 자격을 부여하기 위해 TF 4199는 모든 최적화 프로그램 수정 사항을 사용합니다. 자세한 내용은 이 링크 를 참조하십시오. 한 번에 모든 기능을 사용하면 이상한 부작용이 발생할 수 있으므로 특정 수정 프로그램을 찾을 수있는 경우 자체 수정 프로그램을 사용하는 것이 좋습니다.

OPTION (QUERYTRACEON 4199);를 사용하여 쿼리별로 추적 플래그를 사용할 수 있습니다 .


0

오래된 질문이지만 대답을 보는 것이 완전하지 않은 것은 내가 찾은 해결 방법을 게시 할 것이라고 생각했습니다. 왜 쿼리 최적화 프로그램이에서 balks인지 HASH모르지만 MERGE입력이 정렬되지 않았기 때문에 마음에 들지 않습니다. 2012/14 년

DECLARE @S VARCHAR(1) = '';

    WITH T
        AS (SELECT TOP (2147483647)
                name + @S AS name2,
                *
            FROM   master..spt_values
            ORDER BY name + @S)
    SELECT *
    FROM   T T1
           INNER JOIN T T2
             ON T1.name2 = T2.name2;

다음 계획을 생성합니다.

여기에 이미지 설명을 입력하십시오

cte의 forcing TOP및 the ORDER BY는 데이터 세트에 대한 충분한 지식을 옵티 마이저에게 제공하는 것으로 보입니다 MERGE JOIN.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.