이 쿼리가 인덱스 스풀을 사용하지 않는 이유는 무엇입니까?


23

옵티마이 저의 동작을 더 잘 이해하고 인덱스 스풀 주위의 한계를 이해하기 위해이 질문을하고 있습니다. 1에서 10000까지의 정수를 힙에 넣었다고 가정하십시오.

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

그리고 중첩 루프 조인을 MAXDOP 1다음 과 같이 수행하십시오.

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

이는 SQL Server에 대해 다소 우호적 인 조치입니다. 중첩 루프 조인은 두 테이블에 모두 관련 인덱스가 없을 때 종종 좋은 선택이 아닙니다. 계획은 다음과 같습니다.

나쁜 질문

테이블 스풀에서 100000000 개의 행을 가져 와서 내 컴퓨터에서 쿼리를 수행하는 데 13 초가 걸립니다. 그러나 쿼리 속도가 느린 이유는 알 수 없습니다. 쿼리 최적화 프로그램은 인덱스 스풀을 통해 즉시 인덱스를 작성할 수 있습니다 . 이 쿼리는 인덱스 스풀의 완벽한 후보 인 것 같습니다.

다음 쿼리는 첫 번째 쿼리와 동일한 결과를 반환하고 인덱스 스풀을 가지며 1 초 이내에 완료됩니다.

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

해결 방법 1

이 쿼리에는 인덱스 스풀도 있으며 1 초 이내에 완료됩니다.

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

해결 방법 2

원래 쿼리에 인덱스 스풀이없는 이유는 무엇입니까? 인덱스 스풀을 제공하는 문서화되거나 문서화되지 않은 힌트 또는 추적 플래그가 있습니까? 이 관련 질문을 찾았 지만 내 질문에 완전히 대답하지 못하여이 쿼리에 대해 신비한 추적 플래그를 사용할 수 없습니다.

답변:


20

아시다시피 옵티마이 저의 검색은 완전하지 않습니다. 상황에 맞는 것으로 실제 쿼리에 대한 배당금을 지불하는 것을 시도합니다. 두 개의 단일 열 인덱싱되지 않은 힙 테이블간에 루프 조인을 강요하는 것은 그러한 시나리오가 아닙니다. 즉, 여기에 몇 가지 세부 사항이 있습니다.

SQL Server는 조인에 대한 더 많은 트릭을 알고 있기 때문에 조인에 조기에 적용하는 것을 좋아합니다. 나중에 조인을 다시 적용으로 변환하는 방법을 살펴볼 수 있습니다. 두 개의 상관 매개 변수 (외부 참조) 의 차이점 안쪽에 적합한 색인이있을 때 적용됩니다. 귀하의 예에는 색인이 없으므로 최적화 프로그램이 적용 대상으로의 변환을 탐색하도록 설득되지 않습니다.

간단한 (적용되지 않은) 조인에는 외부 참조 대신 조인 연산자에 조인 조건자가 있습니다. 비적용에 대한 스풀 최적화는 일반적으로 내부 테이블에 술어가없고 결합에만 있기 때문에 게으른 테이블 스풀입니다.

옵티마이 저는 적용을 위해 인덱스를 즉석에서 작성하는 것을 고려하지 않습니다. 오히려 이벤트 순서는 일반적으로 반대입니다. 좋은 인덱스가 존재하기 때문에 적용되도록 변환하십시오.

APPLY쿼리에서 구문 을 사용하여 조인 대신 적용을 권장 할 수 있습니다 . 문서화되지 않은 추적 플래그 (9114)는 옵티마이 저가 논리적 적용을 결합 선행으로 변환하지 않도록 설득함으로써이를 지원할 수있다. 예를 들면 다음과 같습니다.

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

스풀 계획

외부 참조는 선택이 조인의 내부에 적용됨을 의미하기 때문에 인덱스 스풀이 선호됩니다. 이것을 통해 종종 볼 수 SelToIndexOnTheFly있지만 다른 경로가 존재합니다. 내 기사 Eager Index Spool 및 The Optimizer를 참조하십시오 .

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