를 사용하면 select *
읽기 수가 훨씬 적을뿐만 아니라를 사용하는 것보다 훨씬 적은 CPU 시간을 사용 하는 쿼리가 select c.Foo
있습니다.
이것은 쿼리입니다.
select top 1000 c.ID
from ATable a
join BTable b on b.OrderKey = a.OrderKey and b.ClientId = a.ClientId
join CTable c on c.OrderId = b.OrderId and c.ShipKey = a.ShipKey
where (a.NextAnalysisDate is null or a.NextAnalysisDate < @dateCutOff)
and b.IsVoided = 0
and c.ComplianceStatus in (3, 5)
and c.ShipmentStatus in (1, 5, 6)
order by a.LastAnalyzedDate
이 작업은 대부분 표 B에서 2,473,658 개의 논리적 읽기로 끝났습니다. 26,562 개의 CPU를 사용했으며 7,965의 지속 시간을 가졌습니다.
이것은 생성 된 쿼리 계획입니다.
PasteThePlan에서 : https://www.brentozar.com/pastetheplan/?id=BJAp2mQIQ
내가 변경하는 경우 c.ID
에 *
쿼리는 논리적 107,049 상당히 균등 세 테이블 사이에 확산, 읽기 완료. CPU 4,266 개를 사용했으며 지속 시간은 1,147입니다.
이것은 생성 된 쿼리 계획입니다.
PasteThePlan에서 : https://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ
나는 Joe Obbish가 제안한 쿼리 힌트를 다음과 같은 결과와 함께 사용하려고 시도했다.
select c.ID
힌트없이 : https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID
힌트 : https://www.brentozar.com/pastetheplan/ ? ID = B1W ___ N87
select *
힌트없이 : https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select *
힌트 : https://www.brentozar.com/pastetheplan/?id=rJhhudNIQ
OPTION(LOOP JOIN)
힌트와 함께 힌트를 사용하면 힌트가 select c.ID
없는 버전과 비교하여 읽기 수를 크게 줄 였지만 힌트 select *
없이 쿼리 를 읽는 횟수는 여전히 약 4 배 입니다. 추가 OPTION(RECOMPILE, HASH JOIN)
받는 select *
쿼리하면 내가 시도 무엇보다 훨씬 더 펼쳤습니다.
테이블과 사용하여 인덱스에 대한 통계를 업데이트 한 후에 WITH FULLSCAN
는 select c.ID
쿼리가 실행되고 훨씬 더 빨리 :
select c.ID
업데이트를하기 전에 : https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select *
갱신하기 전에 : https://www.brentozar.com/ ? pastetheplan / ID = ryrvodEUX
select c.ID
갱신 후 : https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select *
갱신 후 : https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m
select *
select c.ID
총 지속 시간 및 총 읽기 ( select *
약 절반의 읽기 수) 측면에서 여전히 성능 이 뛰어나지 만 더 많은 CPU를 사용합니다. 전반적으로 업데이트 이전보다 훨씬 더 가깝지만 계획은 여전히 다릅니다.
2016 년 호환성 모드에서 2014 년에 실행되는 2016 년에도 동일한 동작이 나타납니다. 두 계획의 차이를 설명 할 수있는 것은 무엇입니까? "올바른"색인이 작성되지 않았을 수 있습니까? 통계가 약간 오래된 것이 원인 일 수 있습니까?
ON
여러 가지 방법으로 술어를 조인 부분으로 이동하려고 시도 했지만 쿼리 계획은 매번 동일합니다.
인덱스 재 구축 후
쿼리와 관련된 세 개의 테이블에서 모든 인덱스를 다시 작성했습니다. c.ID
여전히 가장 많은 읽기를 수행하고 있지만 (의 두 배 이상 *
) CPU 사용량은 *
버전의 약 절반입니다 . 이 c.ID
버전은 ATable
다음
c.ID
과 같이 정렬하여 tempdb에 유출되었습니다 . : https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
*
: https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ
나는 또한 병렬 처리없이 강제로 작동하려고 시도했으며 그 결과 나에게 가장 우수한 쿼리를 얻었습니다 : https://www.brentozar.com/pastetheplan/?id=SJn9-vuLX
단일 스레드 버전에서는 1,000 번만 주문을 수행하는 큰 인덱스 검색 후에 연산자의 실행 횟수를 알 수 있지만 Parallelized 버전에서는 2,622에서 4,315 사이의 다양한 연산자 실행이 훨씬 더 많이 수행됩니다.
select c.ID
훨씬 빠르게 쿼리를하지만 여전히 몇 가지 추가 작업하고있는select *
힌트없이 쿼리, 수행합니다.