조인 힌트를 추가 할 때 SQL Server 행 예상치가 변경되는 이유는 무엇입니까?


15

몇 가지 테이블을 조인하고 꽤 나쁘게 수행하는 쿼리가 있습니다. 행 추정이 (1000 번) 떨어져 있고 중첩 루프 조인이 선택되어 여러 테이블 스캔이 발생합니다. 쿼리의 모양은 다음과 같이 매우 간단합니다.

SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id 
WHERE t4.id = some_GUID

쿼리를 사용하여 조인 중 하나에 병합 조인을 사용하도록 힌트를 주면 여러 번 더 빠르게 실행됩니다. 이해할 수 있습니다-병합 조인은 조인 된 데이터에 대한 더 나은 옵션이지만 SQL Server는 Nested Loops를 올바르게 선택하는 것으로 추정하지 않습니다.

내가 완전히 이해하지 못하는 것은 왜이 조인 힌트가 모든 계획 운영자에 대한 모든 추정치를 변경합니까? 다른 기사와 서적을 읽음으로써 계획이 작성되기 전에 카디널리티 추정이 수행된다고 가정했기 때문에 힌트를 사용해도 추정이 변경되지 않고 SQL Server에 명시 적으로 특정 물리적 조인 구현을 사용하도록 지시합니다.

그러나 내가 보는 것은 병합 힌트로 인해 모든 추정이 거의 완벽해진다는 것입니다. 통계가 분명히이를 허용한다는 점을 고려할 때 이런 일이 발생하는 이유는 무엇입니까?

UPD : 익명 실행 계획은 여기에서 찾을 수 있습니다 : https://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl=0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0

TF 3604, 9292 및 9204를 사용하여 두 쿼리에서 사용되는 통계를 확인했으며 동일한 통계입니다. 그러나 검색 / 검색된 인덱스는 쿼리마다 다릅니다.

그 외에도 쿼리를 OPTION (FORCE ORDER)실행하여 병합 조인을 사용하는 것보다 훨씬 빠르게 실행하여 모든 조인에 대해 HASH MATCH를 선택했습니다.


3
외부 조인이 있음을 알았지 만 where 절의 테이블을 사용하고 있습니까?
제임스 Z

@JamesZ-예, 나는 그것을 알고 있습니다. 나는 그것에 문제가 있다고 생각하지 않습니다.
Alexander Shelemin

9
@AlexSh 글쎄, 그것은 당신의 외부 조인을 내부 조인으로 변경하기 때문에 그것에 논리적 / 의미 론적 문제가 있습니다.
Aaron Bertrand

답변:


21

다른 기사와 책을 읽음으로써 계획을 세우기 전에 카디널리티 추정을 수행한다고 가정했습니다.

정확히. 초기 카디널리티 추정은 최적화 알고리즘에 의해 선택된 초기 가입 순서에 영향을 미친다 (단순화 및 기타 작업 후) 유도된다.

그러나 후속 탐색 (비용 기반 최적화 중)은 종종 새로운 카디널리티 추정이 계산 될 수 있습니다. 이후의 CE는 다소 '정확'할 수 있습니다. 결과가 과소 평가되면 옵티마이 저는 더 저렴 해 보이지만 실제로는 더 오래 실행되는 계획을 선택할 수 있습니다.

일반적으로 의미 상 동일한 서브 트리에 대한 카디널리티 추정이 동일한 결과를 생성한다는 보장은 없습니다. 결국 통계 프로세스이며 일부 작업은 다른 작업보다 CE 지원이 더 깊습니다.

귀하의 경우에는 또 다른 요인이 있습니다. 최적화 프로그램은 Top을 도입 (또는 이동) 하여 하위 트리 의 행 목표 를 설정 합니다.

조각 계획

추적 플래그 4138 (2008 R2 이상) 을 사용하도록 설정 한 경우 예상과 더 일치하는 추정값을 찾거나 옵티마이 저가 더 이상 중첩 루프를 선택하지 않을 수도 있습니다.

그러나 내가 보는 것은 병합 힌트로 인해 모든 추정이 거의 완벽해진다는 것입니다.

여기에 운의 요소가 있습니다. 사람들은 물리적으로 수행되는 순서대로 쿼리 또는 적어도 조인을 작성하는 경향이 있습니다. 조인 힌트를 사용 FORCE ORDER하면 텍스트 형식과 일치하도록 조인 순서를 수정하고 카디널리티 재 추정을 유발할 수있는 많은 옵티 마이저 탐색 규칙을 해제 할 수 있습니다.

그 외에도 쿼리를 OPTION (FORCE ORDER)실행하여 병합 조인을 사용하는 것보다 훨씬 빠르게 실행하여 모든 조인에 대해 HASH MATCH를 선택했습니다.

이것은 조인 힌트와 동일하지만 실제 조인 연산자의 선택을 제한하지는 않습니다. 다시 말하지만, 쿼리 조인 순서를 논리적으로 쓰면 합리적인 계획을 얻게 될 것입니다. 물론 이런 방식으로 옵티마이 저의 많은 기능을 놓치게되므로보다 일반적인 상황에서는 최적의 결과를 얻지 못할 수 있습니다.

FORCE ORDER아주 조인 순서를 강제하는 것보다 더 넓은 효과를 갖는 매우 강력한 힌트 (지시적)이기 때문에 자주 사용하고 싶지 않을 것입니다 . 예를 들어, 옵티마이 저가 집계를 이동하고 부분 집계를 도입하지 못하게합니다. 나는 매우 예외적 인 상황을 제외하고는 진정한 전문가 튜너를 제외하고는이 힌트를 사용하지 않는 것이 좋습니다.

자세한 분석을 위해서는 지금보다 많은 시간이 필요하며 통계 전용 데이터베이스 사본에 액세스해야합니다.


-10

왼쪽을 부정하는 곳
옵티 마이저에서 왜 어려운가?
3 회 이상의 조인에서 옵티마이 저는 메모리를 보호하므로 방어 및 루프 조인으로
경향이 있습니다. 조인의 조건 또는 조건은 루프 조인으로 들어가는 경향이 있습니다. 매번 발생할 수있는 확실한 증거가 있습니까? 아직도 현실
여러 조인을 사용하면 가능한 곳에서 조인으로 조건을 가져옵니다.

SELECT t1.id
  FROM t1
  JOIN t2 
        ON t1.id = t2.t1_id
  JOIN t3 
        ON t2.id = t3.t2_id
  JOIN t4 
        ON t3.t4_id = t4.id 
       AND t4.id = some_GUID 

또는 더 나은 아직-나는 이것이 당신의 힌트 또는 힘을 충족 시키거나 이길 것이라고 확신합니다

SELECT t1.id
  FROM t1
  JOIN t2 
        ON t1.id = t2.t1_id
  JOIN t3 
        ON t2.id = t3.t2_id
       AND t3.t4_id = some_GUID

힌트의 문제점은 특정 상태의 데이터에 대한 것입니다. 깨끗한 쿼리를 작성하고 옵티마이 저가 작업을 수행하게하십시오. 때로는 올바른 일을하기 위해 더 많은 통계가 필요하지만 잠기 게됩니다.

추정치가 다른 이유 다른 계획. 옵티 마이저에게 전투 기회를 제공하는 쿼리부터 시작하십시오.

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