런타임에 조인이 where 절에 최적화되어 있습니까?


14

이런 쿼리를 작성할 때 ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

SQL 옵티마이 저가 올바른 용어인지 확실하지 않으면 다음과 같이 변환합니다.

select *
from table1 t1, table2 t2
where t1.id = t2.id

본질적으로 SQL Server의 Join 문이 SQL을 작성하는 더 쉬운 방법입니까? 아니면 실제로 런타임에 사용됩니까?

편집 : 거의 항상, 거의 항상 Join 구문을 사용합니다. 무슨 일이 일어 났는지 궁금합니다.


1
"거의"에 대해 자세히 설명해 주시겠습니까? 구식 구문을 언제 사용하고 왜합니까?
Aaron Bertrand

2
차이를 만드는 한 가지 사례는 다음 GROUP BY ALL과 같습니다.
Martin Smith

@MartinSmith 아무도 GROUP BY ALL의도적으로 사용 합니까? :-)
Aaron Bertrand

@AaronBertrand-의심 스럽다! 내가 누군가 그것을 사용하는 것을 본 적이 있다고 생각하지 마십시오.
Martin Smith

답변:


20

그것들은 내부적으로 같은 것으로 무너집니다. 전자는 항상 작성해야합니다 . 더 중요한 것은 왜 중요한가? 실행 계획과 성능면에서 동일합니다 (지저분하지 않다고 가정하면 지연되고 구식 구문으로 처리하기가 더 쉽습니다).

여기에는이 있음을의 AdventureWorks를 사용하지 않는 증거 CROSS JOINfilter진행.


명시 적 조인 :

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


암시 적 조인 :

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


봐봐, 엄마! 동일한 계획, 동일한 결과, 교차 조인 또는 필터가 어디에도 없습니다.

명확성을 위해 SELECT두 경우 모두 운영자에 대한 경고 는 카디널리티에 영향을 미치는 암시 적 변환이며 두 경우 모두 조인과 관련이 없습니다.


20

엄밀히 말하면 두 가지 형식 사이에서 쿼리 최적화 프로그램의 입력에 차이가 있습니다.

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

ISO-89 입력 트리

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

ISO-92 입력 트리

보시다시피, ON절 술어는 현대 구문을 사용하여 조인에 밀접하게 바인딩됩니다. 이전 구문에서는 논리 교차 조인과 관계형 선택 (행 필터)이 있습니다.

쿼리 최적화 프로그램은 최적화 중에 관계형 선택을 조인으로 거의 항상 축소합니다. 즉, 두 형식이 동등한 쿼리 계획을 생성 할 가능성이 높지만 실제 보장은 없습니다.


4

내부 조인의 경우 상호 교환이 가능하지만 외부 조인의 경우 서로 다른 의미를 갖습니다. ON은 일치하고 WHERE는 단순한 필터링입니다. 따라서 ON에서 올바른 JOIN 구문 일치를 유지하는 것이 좋습니다.


4

좋아, 궁금해서 시험을 보았습니다. 다음에 대한 실제 실행 계획이 있습니다.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

나는 그것들을 객체별로 비교했고 그들은 동일했습니다. 최소한 아주 간단한 예를 들어, 그들은 같은 일을했습니다. 나는 또한 IO와 시간 통계를 확인했고 그것들은 똑같을 정도로 충분히 가까웠다.

즉, JOIN구문을 읽기가 쉽고 특히 복잡한 쿼리에서 실수를 할 가능성이 적기 때문에 구문 을 사용해야 합니다. 조인에 대한 *=/ =*구문 OUTER은 SQL-Server 2005에서 이미 제거되었습니다.

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