필요에 따라 수행하지 않은 다소 복잡한 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로만 해제되었으며 두 개의 클러스터 된 인덱스에서 해시 일치로 수행되었습니다.
답변
강제 조인 순서가 쿼리 추정값을 완전히 부정확하게하여 쿼리 시간을 예측할 수없는 것이 정상입니까?
FORCE ORDER를 사용한다고해서 추정치가 부정확하지는 않습니다. 행이 삭제되었습니다. 테이블에서 통계를 강제로 업데이트하면 추정 정확도가 향상 될 수 있습니다.
최적이 아닌 쿼리 성능을 수락하거나 매처럼보고 수동으로 쿼리 힌트를 편집해야한다고 기대해야합니까? 아니면 모든 조인도 암시합니까? .3 초에서 2 초로 큰 타격을받습니다.
FORCE ORDER 힌트를 사용하지 않고 옵티 마이저에게 최상의 계획을 생성하는 데 필요한 정보를 제공하는 것이 바람직합니다. 그렇게함으로써, 그것은 해야 수동 개입없이 더 나은 기본 데이터 분포 변화에 대응. 즉, 데이터의 특성이 카디널리티가 시간별 또는 시간별로 크게 달라질 수있는 경우 계획 지침 을 사용하여 계획이 고정되었는지 확인하십시오.
행을 삭제 한 후 옵티마이 저가 폭발 한 이유는 분명합니까? 예를 들어, “예, 샘플 스캔이 필요했습니다. 데이터 히스토리의 초기에 대부분의 행을 아카이브했기 때문에 샘플에서 희소 한 결과를 얻었으므로 정렬 된 해시 작업의 필요성을 과소 평가했습니다”?
문제 테이블에서 행 수는 언급하지 않았지만 삭제는 다음 중 하나 일 수 있습니다.
- 통계 업데이트를 트리거하기에 충분한 행을 제거하지 않았습니다. 행의 20 %가 수정되었지만 동적 임계 값 을 사용하기 위해 추적 플래그 2371 을 사용하는 옵션이있을 때 발생합니다 .
- 통계 업데이트를 트리거했지만 수집 된 샘플은 대표적이지 않았습니다. WITH FULLSCAN 수동 업데이트를 실행하여이를 수정하십시오 .
또한 구식 매개 변수 스니핑 문제가 발생했을 수 있습니다.이 옵션에는 수많은 옵션이 있습니다. WITH RECOMPILE 은이 큰 쿼리로 지정하는 비싼 옵션 일 수 있지만 프로 시저 및 명령문 레벨 모두에서 조사 할 가치가 있습니다.