이러한 유사한 쿼리가 다른 최적화 단계 (트랜잭션 처리와 빠른 계획)를 사용하는 이유는 무엇입니까?


12

이 연결 항목 의 예제 코드

어디에 버그를 보여줍니다

SELECT COUNT(*)
FROM   dbo.my_splitter_1('2') L1
       INNER JOIN dbo.my_splitter_1('') L2
         ON L1.csv_item = L2.csv_item

올바른 결과를 반환합니다. 그러나 다음은 잘못된 결과를 반환합니다 (2014 년 새로운 카디널리티 추정기를 사용하여)

SELECT
    (SELECT COUNT(*)
    FROM dbo.my_splitter_1('2') L1
     INNER JOIN dbo.my_splitter_1('') L2
        ON L1.csv_item = L2.csv_item)

L2에 대한 결과를 공통 하위 표현식 스풀에 잘못로드하면 L1 결과에 대한 결과를 재생합니다.

두 쿼리의 동작이 왜 다른지 궁금합니다. 추적 플래그 8675는 작동 search(0) - transaction processing하는 것과 실패한 것이 들어간 것을 보여줍니다 search(1) - quick plan.

따라서 추가 변환 규칙의 가용성이 동작의 차이 뒤에 있다고 가정합니다 ( 예 : BuildGbApply 또는 GenGbApplySimple을 사용 하지 않도록 설정하면 수정).

그러나 이러한 매우 유사한 쿼리에 대한 두 계획에서 서로 다른 최적화 단계가 발생하는 이유는 무엇입니까? 내가 읽은 것에서 search (0)적어도 3 개의 테이블이 필요하며 그 조건은 첫 번째 예에서 확실히 충족되지 않습니다.

답변:


7

각 단계에는 입학 조건이 있습니다. "최소한 3 개의 테이블 참조가있는"은 간단한 예제를 제공 할 때 우리가 이야기하는 진입 조건 중 하나이지만 이것이 유일한 것은 아닙니다.

일반적으로 기본 조인 및 공용체 만 0으로 검색 할 수 있습니다. 스칼라 서브 쿼리, 세미 조인 등으로 인해 0이 검색되지 않습니다.이 단계는 실제로 매우 일반적인 OLTP 유형 쿼리 셰이프를위한 것입니다. 덜 일반적인 것들을 탐색하는 데 필요한 규칙은 활성화되어 있지 않습니다. 예제 쿼리에 스칼라 하위 쿼리가 있으므로 입력에 실패합니다.

또한 테이블 참조를 계산하는 방법에 따라 다릅니다. 함수를 사용하여 이것에 대해 깊이 살펴본 적이 없지만 논리가 테이블 값 함수 및 생성하는 테이블 변수를 계산할 수 있습니다. 함수 자체 내에서 테이블 참조를 계산할 수도 있습니다. 확실하지 않습니다. 나는 기능이 모든면에서 열심히 일한다는 것을 알고 있지만.

버그 GenGbApplySimple는 못 생겼습니다. 이 계획 형태는 항상 가능성이 있었지만, 테이블 변수 카디널리티가 100 행으로 변경 될 때까지 비용 문제로 인해 거부되었습니다 USE PLAN.

이전에보고 된 것과 동일한 문제인 새 Connect 항목 에 대해 맞습니다 .

예를 제공하기 위해 다음 쿼리는 검색 0에 적합합니다.

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY U.c1) 
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;

스칼라 하위 쿼리를 포함하도록 약간 변경하면 검색 1로 바로 이동합니다.

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -- Changed!
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.