두 가지 실행 계획을 살펴보면 어느 쪽이 더 나은지에 대한 쉬운 대답이 있습니까? 의도적으로 인덱스를 만들지 않았으므로 무슨 일이 일어나고 있는지 쉽게 알 수 있습니다.
두 번째 계획은 추정 비용이 더 낮기 때문에 제한된 의미에서 '더 나은'것입니다.
데이터 세트가 너무 작아서 옵티마이 저가 대안을 찾는 데 많은 시간을 소비하지 않았습니다. 쿼리의 첫 번째 형태는 초기에 해시 조인과 테이블 스풀을 사용하여 계획을 찾는 것입니다. 해당 계획의 예상 비용이 너무 낮아서 옵티마이 저가 더 나은 것을 찾지 않아도됩니다.
쿼리의 두 번째 형식은 검색 프로세스 초기에 중첩 루프 외부 조인 만 사용하여 계획을 찾고 다시 옵티마이 저가 계획이 충분하다고 결정합니다. 이 계획은 더 싼 것으로 추정됩니다.
(질문 의견에서 언급했듯이) 두 쿼리는 의미 상 동일하지 않습니다. 결과가 데이터베이스의 모든 가능한 미래 상태에 대해 항상 동일하다는 것을 보장 할 수 있지만 옵티마이 저가 그러한 가정을 할 수없는 경우에는 이것이 중요하지 않을 수 있습니다. 모든 상황에서 SQL에 지정된 것과 동일한 결과를 생성하도록 보장 된 계획 만 생성합니다.
중첩 구문도 쿼리 동작을 수정한다는 것을 알았습니다.
'중첩 구문'은 전체 ANSI 조인 구문 사양의 한 측면 일뿐입니다. 보다 복잡한 조인 패턴에 대해 전체 논리적 사양을 사용하려면 사양에서 괄호 및 FROM
절 하위 쿼리를 허용합니다 (선택 사항) .
괄호를 사용하여 동일한 ANSI 구문을 사용 하여 쿼리를 작성할 수 있습니다 .
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN
(
dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;
이 양식 논리적 인 요구 사항은 왼쪽에서 가입하는 것을 명확하게 보여줍니다 Autos
받는 결과를 내면 가입 Manufacturers
에 Models
. 선택적 괄호를 생략하면 '중첩'이라는 형식이됩니다.
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
ON M.ModelID = A.ModelID;
이것은 다른 구문이 아닙니다. 선택적인 괄호를 생략하고 조금 다시 포맷하는 것입니다.
Martin이 언급했듯이이 경우 내부 조인과 오른쪽 외부 조인을 사용하여 논리적 요구 사항을 표현할 수도 있습니다.
SELECT
A.*,
M.*,
N.*
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
ON A.ModelID = M.ModelID;
위의 세 가지 쿼리 형식은 모두 동일한 ANSI 조인 구문을 사용합니다. 세 가지 모두 제공된 데이터 세트를 사용하여 동일한 물리적 실행 계획을 생성합니다.
이전 질문에 대한 답변에서 언급했듯이 정확히 동일한 논리적 요구 사항을 나타내는 쿼리가 항상 동일한 실행 계획을 생성하지는 않습니다. 어떤 논리 쿼리 형식을 선호 하는가는 주로 스타일 문제입니다. 하나의 특정 스타일과 '더 나은'쿼리 계획 간에는 일반적으로 상관 관계가 없습니다. 새 쿼리가 실제로 원래 쿼리와 동일하지 않은 경우 특정 계획을 얻기 위해 쿼리를 다시 작성하지 않는 것이 좋습니다.
SQL 표준은 FROM
절 하위 쿼리 도 허용 하므로 동일한 쿼리 사양을 작성하는 또 다른 방법은 다음과 같습니다.
SELECT *
FROM dbo.Autos AS A
LEFT JOIN
(
SELECT
N.ManufacturerID,
ManufacturerName = N.Name,
M.ModelID,
ModelName = M.Name
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) AS R1
ON R1.ModelID = A.ModelID;
전통적인 구문을 사용하여`제조업체의 조인을 외부 조인으로 변경해야합니다.하지만 쿼리 계획이 변경됩니다.
이것은 아마도 쿼리의 의미를 바꿀 것입니다.이 경우 기술적으로 유효한 대안이 아닙니다 (그러나 귀하의 질문에 대한 ypercube 의 의견 참조 ).
ANSI 조인 구문의 (선택적) 괄호는 이와 같이보다 복잡한 조인 요구 사항에 정확하게 적용되므로 필요한 경우이를 사용하는 것을 두려워해서는 안됩니다.