ON과 WHERE의 인덱스 성능


26

나는 두 개의 테이블이

@T1 TABLE
(
    Id INT,
    Date DATETIME
)

@T2 TABLE
(
    Id INT,
    Date DATETIME
)

이 테이블에는 (Id, Date)에 비 클러스터형 인덱스가 있습니다.

그리고 나는이 테이블에 합류합니다

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
WHERE 
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

이것은 또한 다음과 같이 쓸 수 있습니다

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
    AND
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

내 질문은이 두 쿼리 중 더 나은 성능을 제공하는 이유와 이유는 무엇입니까? 아니면 평등합니까?


1
실제로 모든 필드를 다루는 클러스터되지 않은 인덱스 로 클러스터링 된 인덱스가 없는 @table 변수가 있습니까? 아니면 단순화입니까?
레무스 루사 누

1
극도의 단순화
Erik Bergstedt 2016 년

답변:


32

성능은 동일합니다. 옵티마이 저는이를 인식하고 동일한 계획을 작성합니다.

반면에 나는 그들이 동등하다고 말하지 않을 것입니다. 질문 의 첫 번째 형태 는 훨씬 더 읽기 쉽고 일반적으로 예상됩니다.

내가 가지고있는 일부 테이블을 사용하는 예제의 경우 쿼리 작성 방법에 관계없이 실행 계획이 정확히 동일하다는 것을 알 수 있습니다.

자신의 테이블과 데이터 세트에 대한 쿼리 계획을 결정하여 상황에서 어떤 일이 발생하는지 확인할 수 있어야합니다.

SELECT * FROM salestable , custtable 
WHERE salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable 
JOIN  custtable 
ON salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable JOIN custtable 
ON salestable.custaccount = custtable.accountnum 
WHERE salestable.dataareaid = custtable.dataareaid

이러한 실행 계획을 제공합니다

여기에 이미지 설명을 입력하십시오


나는 첫 번째 양식이 읽기 쉽다는 것에 동의하며, 따라서 그것들은 동일하다는 것을 안다. 앞으로이 양식 만 사용하겠습니다.
Erik Bergstedt 2016 년

@ErikBergstedt 내 대답을 편집했습니다. 실행 계획을 볼 때 자신의 데이터 집합 및 테이블 구조에 대해 이것을 쉽게 확인할 수 있어야합니다.
Tom V-Team Monica

그래, 내가 했어. 고맙습니다. 기존 답변을 찾지 못했기 때문에 2 차 의견 만 찾고있었습니다.
Erik Bergstedt 2016 년

참고 :이 경우에만 동일합니다 INNER JOIN. 당신이 OUTER JOIN안으로 던지면 그들은 결정적으로 동일하지 않습니다.
케네스 피셔

22

의미 적으로 동일하며 옵티마이 저는이 사실을 인식하고 동일한 계획을 생성하는 데 어려움이 없어야합니다.

나는 두 테이블을 모두 참조하는 ON조건과에 하나의 테이블을 참조 하는 조건을 넣는 경향이 WHERE있습니다.

대한 OUTER JOINS조건을 이동하지만 의미에 영향을 줄 수 있습니다.


7

간단한 경우에는 동일합니다. 그러나 여러 조인이있는 매우 복잡한 쿼리에는 계획이 크게 다릅니다. 최근에 작업 한 한 테이블은 약 6 백만 개의 행이 약 20 개의 다른 테이블에 연결된 테이블로 시작했습니다. 이 테이블의 첫 번째 조인 만 내부 조인이었고 다른 모든 조인은 외부 조인이되었습니다. where 절의 필터는 다음과 같이 매개 변수화되었습니다.

WHERE table1.begindate >= @startdate AND table1.enddate < @enddate 

이 필터는 나중에 대신 계획에서 사용되었습니다. 이러한 조건을 첫 번째 내부 조인으로 옮길 때 계획에서 필터를 초기에 적용하여 결과 세트를 제한하고 CPU 및 경과 시간이 약 310 % 감소함에 따라 계획이 크게 변경되었습니다. 따라서 많은 SQL Server 질문과 마찬가지로 다릅니다.


2
답변이 다른 모든 것과 모순되는 것처럼 실행 계획 다이어그램의 스크린 샷과 같은 세부 정보를 추가 할 수 있습니까?
Kenny Evitt

2
계획에 옵티 마이저 제한 시간이 표시 되었습니까?
Martin Smith

CPU로드가 어떻게 100 % 이상 떨어질 수 있습니까?
Michael Green

2

일반적으로 필터를 넣는 위치에 차이가 있습니다.
Tom V는 Optimizer가 쿼리가 동일하다는 것을 인식하고 동일한 계획을 제시한다고 말하지만 항상 그런 것은 아닙니다. 사용중인 SQL 버전, 쿼리의 복잡도 및 옵티마이 저가 쿼리가 결정하는 전체 배치에 얼마나 중요한지에 따라 다릅니다.

옵티마이 저는 배치의이 부분이 최상의 계획을 세우기 위해 충분한 시간을 소비 할 가치가 없다고 결정할 수 있습니다. 일반적으로 쿼리가 WHERE 절 대신 ON 절에서 작업해야하는 데이터 양을 줄이는 조건을 설정하면 성능이 향상됩니다 (가능한 경우 외부 조인으로이를 수행하면 카티 전 곱이 발생하므로 )

가끔 SQL Developer가 WHERE 절에서 필터를 발견하는 것이 약간 쉽지만 ON 절에서 필터를 사용하면 런타임에서 시간이 줄어드는 큰 테이블을 작업했습니다.

따라서 절에 쿼리가 읽을 행 수를 대폭 줄일 수있는 가능성이 있다면 옵티마이 저가 더 나은 계획을 선택할 수 있도록 항상 ON 절에 넣습니다.


1

일반적인 상황에서 필터 조건은 WHERE 또는 JOIN 절에서 지정할 수 있습니다. OUTER JOIN 우선 순위에 영향을 줄 수 있거나 (아래 참조) 필터가 해당 테이블에 매우 특정한 경우 (예 : 테이블에 특정 행의 하위 집합을 지정하기 위해 TYPE = 12)가 아니면 필터를 WHERE 아래에 배치하는 경향이 있습니다.

반면에 ON 및 WHERE 절을 모두 사용하여 필터 조건과 달리 결합 조건을 지정할 수 있습니다. INNER 조인 만 사용하는 한 일반적인 상황에서 어떤 것을 사용하든 상관 없습니다.

그러나 OUTER 조인을 사용하는 경우 큰 차이가 생길 수 있습니다. 예를 들어 두 테이블 (t1과 t2) 사이에 OUTER JOIN을 지정하고 WHERE 절에서 테이블 사이의 eqijoin 관계 (예 : t1.col = t2.col)를 지정하는 경우 OUTER 조인을 INNER 조인으로 변환했습니다! 이는 WHERE를 사용하여 ON 절을 사용하지 않고 동등 조인 (또는 사용되지 않는 * = 구문을 사용하여 버전에 따라 OUTER 조인)을 지정할 수 있고 WHERE가 테이블 사이의 내부 동등 조인을 나타내는 경우 OUTER를 대체합니다. 가입하십시오 (있는 경우).

원래 질문은 조인 유형이 종종 문제가되지 않아야하는 필터에 관한 것이지만 조인은 필터 역할을 할 수 있으며 이러한 상황에서 조인 조건의 배치는 확실히 중요 할 수 있습니다.


-1

INNER JOIN을 사용하면 스타일 문제입니다.

그러나 OUTER JOIN에서는 훨씬 더 흥미로워집니다. OUTER JOIN이있는 쿼리와 ON 절 및 WHERE 절의 조건 간의 차이점을 탐색해야합니다. 결과 집합이 항상 동일한 것은 아닙니다. 예를 들어

OUTER JOIN dbo.x ON a.ID = x.ID ... WHERE x.SomeField IS NOT NULL

와 동일

INNER JOIN dbo.x ON a.ID = x.ID AND x.SomeField IS NOT NULL

8
결과가 다른 경우 (물론) 성능을 비교하는 요점은 무엇입니까?
ypercubeᵀᴹ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.