다른 구문을 사용하여 쿼리를 표현하면 비 클러스터형 인덱스를 사용하려는 최적화 프로그램에 의사를 전달하는 데 도움이 될 수 있습니다. 아래 양식을 통해 원하는 계획을 찾으십시오.
SELECT
[ID],
[DeviceID],
[IsPUp],
[IsWebUp],
[IsPingUp],
[DateEntered]
FROM [dbo].[Heartbeats]
WHERE
[ID] IN
(
-- Keys
SELECT TOP (1000)
[ID]
FROM [dbo].[Heartbeats]
WHERE
[DateEntered] >= CONVERT(datetime, '2011-08-30', 121)
AND [DateEntered] < CONVERT(datetime, '2011-08-31', 121)
);
비 클러스터형 인덱스에 힌트가있는 경우 생성 된 계획과 해당 계획을 비교하십시오.
SELECT TOP (1000)
*
FROM [dbo].[Heartbeats] WITH (INDEX(CommonQueryIndex))
WHERE
[DateEntered] BETWEEN '2011-08-30' and '2011-08-31';
계획은 본질적으로 동일합니다 (키 조회는 클러스터 된 인덱스에 대한 검색에 지나지 않습니다). 두 계획 양식 모두 비 클러스터형 인덱스에서 한 번의 검색 만 수행하고 클러스터형 인덱스에서 최대 1000 개의 조회를 수행합니다.
중요한 차이점은 최상위 연산자의 위치에 있습니다. 두 탐색 사이에 배치 된 Top은 옵티마이 저가 두 탐색 조작을 논리적으로 동등한 클러스터 색인 스캔으로 대체하지 못하게합니다. 옵티마이 저는 논리적 계획의 일부를 동등한 관계형 조작으로 대체하여 작동합니다. Top은 관계 연산자가 아니므로 다시 쓰기를 수행하면 클러스터형 인덱스 스캔으로 변환되지 않습니다. 옵티마이 저가 상위 운영자를 재배치 할 수있는 경우 비용 추정이 작동하는 방식 때문에 검색 + 조회보다 스캔을 선호합니다.
스캔 및 탐색 비용
매우 높은 수준에서 스캔 및 검색에 대한 옵티마이 저의 비용 모델은 매우 간단합니다. 320 개의 랜덤 검색이 스캔에서 1350 페이지를 읽는 것과 동일한 비용을 추정합니다 . 이것은 현대의 특정 I / O 시스템의 하드웨어 기능과 거의 유사하지는 않지만 실용적인 모델로서 합리적으로 잘 작동합니다.
이 모델은 또한 여러 가지 단순화 된 가정을합니다. 가장 중요한 것은 모든 쿼리가 이미 캐시에 데이터 나 인덱스 페이지없이 시작되는 것으로 가정한다는 것입니다. 이는 모든 I / O가 물리적 I / O를 초래한다는 사실을 의미하지만 실제로는 거의 해당되지 않습니다. 콜드 캐시 (cold cache)를 사용하더라도 프리 페치 및 미리 읽기는 쿼리 프로세서가 필요할 때 실제로 필요한 페이지가 메모리에있을 가능성이 높다는 것을 의미합니다.
메모리에없는 행에 대한 첫 번째 요청으로 인해 전체 페이지가 디스크에서 페치됩니다. 동일한 페이지에서 행에 대한 후속 요청은 실제 I / O를 발생시키지 않을 가능성이 높습니다. 원가 계산 모델에는 이와 같은 효과를 고려하는 논리가 포함되어 있지만 완벽하지는 않습니다.
이러한 모든 것 (및 그 이상)은 옵티마이 저가 예상보다 빨리 스캔으로 전환하는 경향이 있음을 의미합니다. 실제 작업 결과 인 경우 임의 I / O는 '순차적'I / O보다 '훨씬 비쌉니다'-메모리의 페이지에 액세스하는 것은 실제로 매우 빠릅니다. 물리적 읽기가 필요한 경우에도 스캔으로 인해 조각화로 인해 순차 읽기가 발생하지 않을 수 있으며 패턴이 본질적으로 순차적이되도록 탐색이 배치 될 수 있습니다. 또한 최신 I / O 시스템 (특히 솔리드 스테이트)의 성능 변화 특성과 모든 것이 매우 흔들 리기 시작합니다.
행 목표
계획에 최고 운영자가 있으면 원가 계산 방식이 수정됩니다. 옵티마이 저는 스캔을 사용하여 1000 개의 행을 찾는 것이 전체 클러스터 된 인덱스를 스캔 할 필요가 없다는 것을 알기에 충분히 똑똑합니다. 1000 개의 행이 발견되는 즉시 중지 될 수 있습니다. Top 연산자에서 1000 행의 '행 목표'를 설정하고 통계 정보를 사용하여 행 소스에서 필요한 행 수를 추정하기 위해 통계 정보를 사용합니다 (이 경우 스캔). 이 계산에 대한 자세한 내용은 여기에 썼습니다 .
이 답변의 이미지는 SQL Sentry Plan Explorer를 사용하여 작성되었습니다 .