필요에 따라 수행하지 않은 다소 복잡한 SQL Server 2008 쿼리 (약 200 줄의 상당히 밀도가 높은 SQL)가 있습니다. 시간이 지남에 따라 성능은 약 0.5 초에서 약 2 초로 떨어졌습니다.
실행 계획을 살펴보면 조인을 재정렬하여 성능을 향상시킬 수 있음이 분명했습니다. 나는 그것을했다. .. 약 .3 초까지. 이제 쿼리에 "OPTION FORCE ORDER"힌트 가 있으며 수명은 좋습니다.
오늘 함께 데이터베이스를 정리합니다. 행을 삭제하는 것을 제외하고 관련 데이터베이스에서 아무 조치도 취하지 않고 행의 약 20 %를 아카이브 합니다. 실행 계획이 TOTALLY hosed 됩니다. 특정 하위 트리가 반환 할 행 수를 완전히 잘못 판단하고 (예 : a)를 바꿉니다.
<Hash>
와
<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>
이제 쿼리 시간이 약 .3 초에서 약 18 초로 급증합니다. (!) 행을 삭제했기 때문에. 쿼리 힌트를 제거하면 약 2 초 쿼리 시간으로 돌아갑니다. 더 좋지만 더 나쁩니다.
데이터베이스를 여러 위치와 서버로 복원 한 후 문제를 재현했습니다. 각 테이블에서 약 20 %의 행을 삭제하면 항상이 문제가 발생합니다.
- 강제 조인 순서가 쿼리 추정값을 완전히 부정확하게하여 쿼리 시간을 예측할 수없는 것이 정상입니까?
- 최적이 아닌 쿼리 성능을 수락하거나 매처럼보고 수동으로 쿼리 힌트를 편집해야한다고 기대해야합니까? 아니면 모든 조인도 암시합니까? .3 초에서 2 초로 큰 타격을받습니다.
- 행을 삭제 한 후 옵티마이 저가 폭발 한 이유는 분명합니까? 예를 들어, "예, 샘플 스캔이 필요했습니다. 데이터 히스토리의 초기에 대부분의 행을 아카이브했기 때문에 샘플에서 희소 한 결과를 얻었으므로 정렬 된 해시 작업의 필요성을 과소 평가했습니다"?
실행 계획을 보려면 게시 할 수있는 위치를 제안하십시오. 그렇지 않으면 가장 멋진 비트를 샘플링했습니다. 여기에 잘못된 추정의 기본이 있으며, parens의 숫자는 (추정 : 실제) 행입니다.
/ Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
\ NonClustered Index Seek (1:7229)
내부 루프는 908 개의 행을 스캔하지만 52,258,441을 스캔합니다. 정확하다면이 분기는 12 초가 아닌 약 2ms 동안 실행되었을 것입니다. 행을 삭제하기 전에이 내부 조인 추정은 총계 2로만 해제되었으며 두 개의 클러스터 된 인덱스에서 해시 일치로 수행되었습니다.