2012-05-15 2 views
5

검색 값을 바꿀 때 성능이 심각하게 저하되는 이중 자체 조인 쿼리가 있습니다. "XYZ"검색 값의 순서에 따라 SQL 쿼리 성능이 저하됩니다.

-- 500,000 i/o & 500ms execution 
select 
    fooA.ID 
    , fooB.ID 
from 
    foo AS fooA 
    INNER JOIN bar AS barA ON fooA.barID = barA.barID 
    INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join 
    INNER JOIN bar AS barB ON fooB.barID = barB.barID 
where 
    barA.value = 'xyz' 
    AND barB.value = '60' 

-- 5,000 i/o & 5ms execution 
select 
    fooA.ID 
    , fooB.ID 
from 
    foo AS fooA 
    INNER JOIN bar AS barA ON fooA.barID = barA.barID 
    INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join 
    INNER JOIN bar AS barB ON fooB.barID = barB.barID 
where 
    barA.value = '60' 
    AND barB.value = 'xyz' 
  • 값은 "줄"테이블에 15 만 번 나열됩니다.
  • 값 "60"은 "막대"테이블에 500 번 나열됩니다.
  • 첫 번째 나열된 검색 값에 따라 가장 안쪽 루프가 150,000 행 또는 500 행을 반환한다는 점을 제외하면 쿼리 계획은 동일합니다.
  • 검색은 클러스터되지 않은 인덱스에 대한 검색을 수행합니다.
  • FULLSCAN을 사용하여 두 테이블의 통계를 모두 업데이트했습니다.

SQL 쿼리 최적화 프로그램이 두 인스턴스 모두에서 쿼리 계획의 가장 안쪽에있는 조인이 최소한의 행 집합이어야한다는 것을 올바르게 식별하지 않는 이유는 무엇입니까?

+0

쿼리의 행 수를 항상 가장 먼저 제한하는 조건을 사용하십시오. 그것의 일반적인 어림짐작. – JonH

+1

가능한 답 : 쿼리 매개 변수화, 매개 변수 스니핑 및 계획 재사용. –

+0

id 테이블을 foo 및 bar 테이블에 기본 키로 만들 수 있습니까? –

답변

3

SQL Server는 쿼리가 실행될 때마다 쿼리를 다시 컴파일하지 않습니다. 이 작업은 한 번 수행되며 처음 보는 정확한 값에 최적화되어 있습니다. 캐시 된 불행한 계획이 있다고 생각합니다.

끝에 OPTION (RECOMPILE)을 추가하십시오.

+0

나는 이것을 덧붙여서 아무런 변화가 없었다. 가장 안쪽에있는 조인에서 예상되는 행 수는 두 쿼리 계획 모두 2,500이지만 실제 값은 크게 다릅니다. –

+0

이상합니다. 평등 일치에 대한 인덱스의 카디널리티 추정은 일반적으로 매우 정확합니다. 찾고있는 테이블에는 매우 적은 수의 행이 포함되어 있습니까? – usr

+0

나는 여기에서 문제를 일으킬 수있는 것을 전혀 보지 못했습니다. 두 가지 실제 실행 계획의 스크린 샷을 게시 할 수 있습니까? – usr

관련 문제