클러스터형 인덱스 스캔 실행 횟수가 왜 이렇게 높습니까?


15

하나의 쿼리 계획이 클러스터 된 인덱스 스캔을 1316 회 실행하고 다른 쿼리는 1 회 실행한다는 점을 제외하고 동일한 쿼리 계획을 생성하는 두 개의 유사한 쿼리가 있습니다.

두 쿼리의 유일한 차이점은 날짜 기준이 다릅니다. 장기 실행 쿼리는 실제로 날짜 기준을 좁히고 더 적은 데이터를 가져옵니다.

두 쿼리 모두에 도움이 될 몇 가지 인덱스를 식별했지만 클러스터 된 인덱스 스캔 연산자가 1 번 실행되는 쿼리와 거의 동일한 쿼리에서 1316 번 실행되는 이유를 이해하고 싶습니다.

스캔중인 PK의 통계를 확인했으며 비교적 최신 상태입니다.

원래 검색어 :

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

이 계획을 생성합니다. 여기에 이미지 설명을 입력하십시오

날짜 범위 기준을 좁힌 후 :

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

이 계획을 생성합니다. 여기에 이미지 설명을 입력하십시오


이미지 파일 대신 코드 블록으로 쿼리를 복사 / 붙여 넣을 수 있습니까?
Eric Humphrey-lotsahelp

물론-각 계획을 생성하는 쿼리를 추가했습니다.
Seibar

클러스터형 인덱스 스캔은 어떤 테이블에서 발생합니까?
Eric Humphrey-lotsahelp

클러스터형 인덱스 스캔은 왼쪽 조인 (PostNFIRSSummary)의 하위 쿼리에 있습니다
Seibar

1
아마도 통계가 마지막으로 업데이트되었을 때 FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'기준을 충족하는 행이 0 개 또는 1 개 뿐이고 그 이후로 해당 범위에 삽입 수가 불균형했습니다. 해당 날짜 범위에 대해 1.07의 실행 만 필요하다고 추정합니다. 실제로는 1,316 개가 아닙니다.
Martin Smith

답변:


9

스캔 후 JOIN은 단서를 제공합니다. 마지막 조인의 한쪽에 행이 적을수록 (물론 오른쪽에서 왼쪽으로 읽음) 옵티마이 저는 "해시 조인"이 아닌 "중첩 루프"를 선택합니다.

그러나 이것을보기 전에 Key Lookup과 DISTINCT를 제거하는 것이 목표입니다.

  • 키 조회 : FIR_Incident에 대한 색인 (FI_IncidentDate, incidentid)이 다른 방법으로 다루어야합니다 . 또는 둘 다 가지고 있고 어느 것이 더 자주 사용되는지 확인하십시오 (둘 다있을 수 있음)

  • DISTINCT결과입니다 LEFT JOIN ... IS NOT NULL. 옵티마이 저가 이미 제거했지만 (계획은 최종 JOIN에 "왼쪽 세미 조인"이 있음) 명확성을 위해 EXISTS를 사용합니다.

다음과 같은 것 :

select 
    F.IncidentID
from 
    FIR_Incident F
where 
    exists (SELECT * FROM postnfirssummary P
           WHERE P.incident_id = F.incidentid)
    AND
    F.FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'

또한 계획 지침 과 JOIN 힌트를 사용하여 SQL Server가 해시 조인을 사용하도록 할 수 있지만 먼저 정상적으로 작동하도록하십시오. 가이드 나 힌트는 아마도 데이터에 유용하기 때문에 시간 테스트를 거치지 않을 것입니다. 미래가 아니라 지금 실행중인 쿼리

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