IT story

ANSI JOIN과 non-ANSI JOIN 쿼리가 다르게 수행됩니까?

hot-time 2020. 12. 25. 09:30
반응형

ANSI JOIN과 non-ANSI JOIN 쿼리가 다르게 수행됩니까?


~ 7000 줄의 T-SQL 저장 프로 시저에 비즈니스 로직이 있으며 대부분 다음 JOIN 구문이 있습니다.

SELECT A.A, B.B, C.C
FROM aaa AS A, bbb AS B, ccc AS C
WHERE
    A.B = B.ID
AND B.C = C.ID
AND C.ID = @param

이러한 쿼리를 다음으로 대체하면 성능이 향상됩니까?

SELECT A.A, B.B, C.C
FROM aaa AS A
JOIN bbb AS B
   ON A.B = B.ID
JOIN ccc AS C
   ON B.C = C.ID
   AND C.ID = @param

아니면 동일합니까?


두 번째 쿼리는 ANSI-92 SQL 구문이고 첫 번째는 조인 절을 통합하지 않은 이전 SQL 구문이라는 점을 제외하면 두 쿼리는 동일합니다. 확인하고 싶더라도 정확히 동일한 내부 쿼리 계획을 생성해야합니다.

여러 가지 이유로 ANSI-92 구문을 사용해야합니다.

  • JOIN 절을 사용하면 관계 논리와 필터 논리 (WHERE)가 분리되므로 더 명확하고 이해하기 쉽습니다.
  • 이 특정 쿼리에서는 문제가되지 않지만 이전 외부 조인 구문 (+ 사용)이 모호하고 쿼리 결과가 구현에 따라 달라 지거나 쿼리를 전혀 해결할 수없는 몇 가지 상황이 있습니다. ANSI-92에서는 발생하지 않습니다.
  • 대부분의 개발자와 dba는 오늘날 ANSI-92를 사용하므로 표준을 따라야하기 때문에 좋은 습관입니다. 확실히 모든 최신 쿼리 도구는 ANSI-92를 생성합니다.
  • @gbn이 지적했듯이 우발적 인 교차 조인을 피하는 경향이 있습니다.

필자는 이전 구문에 약간의 개념적 이점이 있기 때문에 한동안 ANSI-92에 저항했습니다. SQL을 필터링 작업에 뒤 따르는 모든 테이블의 대량 데카르트 조인으로 생각하기 쉽기 때문에 유용 할 수있는 정신적 기법입니다. SQL 쿼리가 수행하는 작업을 파악합니다. 그러나 나는 몇 년 전에 시대에 맞춰 움직여야한다고 결정했고 상대적으로 짧은 조정 기간 후에 지금은 그것을 강력하게 선호합니다. 주로 위에 주어진 첫 번째 이유 때문입니다. ANSI-92 구문에서 벗어나거나 옵션을 사용하지 않아야하는 유일한 위치는 암시 적으로 위험한 자연 조인을 사용하는 것입니다.


두 번째 구문은 SQL 커뮤니티에서 "고정 조인 구문"으로 알려져 있습니다. 첫 번째 구조 AFAIK는 널리 받아 들여지는 이름을 가지고 있지 않으므로 '이전 스타일'내부 조인 구문이라고합시다.

일반적인 인수는 다음과 같습니다.

'전통적인'구문의 장점 : 술어는 WHERE쿼리를 일반적으로 만드는 순서에 관계없이 절에서 물리적으로 그룹화되며 특히 n- 항 관계는 읽고 이해하기 더 쉽습니다 ( ON중첩 구문 절은 술어를 분산시킬 수 있습니다. 따라서 시각적 거리에서 하나의 테이블 또는 기둥의 모양을 찾아야합니다.

'전통적인'구문의 단점 : 'join'술어 중 하나를 생략 할 때 구문 분석 오류가 없으며 결과는 카티 전 곱 ( CROSS JOIN중첩 구문에서 라고 함 )이며 이러한 오류를 감지하고 디버그하기가 까다로울 수 있습니다. 또한 'join'술어와 'filtering'술어는 WHERE에서 물리적으로 함께 그룹화되어 서로 혼동 될 수 있습니다.


좋아요, 그들은 똑같이 실행합니다. 동의했습니다. 나는 많은 사람들과 달리 오래된 규칙을 사용합니다. SQL-92가 "이해하기 쉽다"는 것은 논쟁의 여지가 있습니다. 40 년 동안 프로그래밍 언어를 작성해온 저는 다른 관습보다 먼저 '읽기 쉬움'이 '시력'으로 시작된다는 것을 알고 있습니다 (여기서는 용어를 잘못 사용했지만 제가 사용할 수있는 가장 좋은 문구입니다). SQL을 읽을 때 가장 먼저 염두에 두는 것은 어떤 테이블이 관련되고 어떤 테이블 (대부분)이 그레인을 정의하는지입니다. 그런 다음 데이터에 대한 관련 제약 조건에 관심이 있고 선택한 속성이 있습니다. SQL-92는 대부분 이러한 아이디어를 분리하지만 노이즈 단어가 너무 많아 마음의 눈이이를 해석하고 처리해야하며 SQL을 읽는 속도가 느려집니다.

SELECT Mgt.attrib_a   AS attrib_a
      ,Sta.attrib_b   AS attrib_b
      ,Stb.attrib_c   AS attrib_c
FROM   Main_Grain_Table  Mgt
      ,Surrounding_TabA  Sta
      ,Surrounding_tabB  Stb
WHERE  Mgt.sta_join_col  = Sta.sta_join_col
AND    Mgt.stb_join_col  = Stb.stb_join_col
AND    Mgt.bus_logic_col = 'TIGHT'

시력! 새 속성에 대한 쉼표를 앞에 넣으면 코드 주석도 더 쉬워집니다. 함수와 키워드에 특정 케이스를 사용합니다. 테이블에 특정 케이스를 사용합니다. 속성에 특정 케이스를 사용합니다. 수직으로 정렬 연산자 및 작업을 정렬합니다. FROM에서 첫 번째 테이블을 만듭니다. 데이터의 단위를 나타냅니다. WHERE의 첫 번째 테이블을 조인 제약 조건으로 만들고 구체적이고 엄격한 제약 조건이 맨 아래로 떠오르게합니다. 데이터베이스의 모든 테이블에 대해 3 자 별명을 선택하고 테이블을 참조하는 모든 곳에서 별명을 사용하십시오. 이 별칭을 해당 테이블의 (많은) 인덱스에 대한 접두사로 사용해야합니다. 6 개 중 1 개 1/2 다스 개, 맞죠? 아마도. 그러나 ANSI-92 규칙을 사용하더라도 (내가 가지고 있고 경우에 따라 계속할 것입니다) 시력 원칙을 사용하여 마음에 드는 수직 정렬을 사용하십시오. '


둘 다 실행하고 쿼리 계획을 확인하십시오. 그들은 한다 동일.


두 쿼리 동일합니다. 첫 번째는 비 ANSI JOIN 구문을 사용하고 두 번째는 ANSI JOIN 구문을 사용합니다. ANSI JOIN 구문을 고수하는 것이 좋습니다.

예, LEFT OUTER JOIN (btw는 ANSI JOIN 구문이기도 함)은 조인하려는 테이블에 일치하는 레코드가 없을 가능성이있을 때 사용하려는 것입니다.

참조 : SQL Server의 조건부 조인


내 생각에 FROM 절은 SELECT 절이 작동하기 위해 행에 필요한 열을 결정하는 곳입니다. 계산에 필요한 동일한 행, 값을 가져 오는 비즈니스 규칙이 표현되는 곳입니다. 비즈니스 규칙은 송장이있는 고객이 될 수 있으며 결과적으로 책임 고객을 포함한 송장 행이 생성됩니다. 또한 클라이언트와 동일한 우편 번호에있는 장소 일 수 있으므로 서로 가까운 장소 및 클라이언트 목록이 생성됩니다.

결과 세트에서 행의 중심성을 계산하는 곳입니다. 결국, 우리는 RDBMS에있는 목록의 은유를 보여줍니다. 각 목록에는 주제 (엔티티)가 있고 각 행은 엔터티의 인스턴스입니다. 행 중심이 이해되면 결과 집합의 엔터티가 이해됩니다.

The WHERE clause, which conceptually executes after the rows are defined in the from clause, culls rows not required (or includes rows that are required) for the SELECT clause to work on.

Because join logic can be expressed in both the FROM clause and the WHERE clause, and because the clauses exist to divide and conquer complex logic, I choose to put join logic that involves values in columns in the FROM clause because that is essentially expressing a business rule that is supported by matching values in columns.

i.e. I won't write a WHERE clause like this:

 WHERE Column1 = Column2

I will put that in the FROM clause like this:

 ON Column1 = Column2

Likewise, if a column is to be compared to external values (values that may or may not be in a column) such as comparing a postcode to a specific postcode, I will put that in the WHERE clause because I am essentially saying I only want rows like this.

i.e. I won't write a FROM clause like this:

 ON PostCode = '1234'

I will put that in the WHERE clause like this:

 WHERE PostCode = '1234'

ANSI syntax does enforce neither predicate placement in the proper clause (be that ON or WHERE), nor the affinity of the ON clause to adjacent table reference. A developer is free to write a mess like this

SELECT
   C.FullName,
   C.CustomerCode,
   O.OrderDate,
   O.OrderTotal,
   OD.ExtendedShippingNotes
FROM
   Customer C
   CROSS JOIN Order O
   INNER JOIN OrderDetail OD
      ON C.CustomerID = O.CustomerID
      AND C.CustomerStatus = 'Preferred'
      AND O.OrderTotal > 1000.0
WHERE
   O.OrderID = OD.OrderID;

Speaking of query tools who "will generate ANSI-92", I'm commenting here because it generated

SELECT 1
   FROM DEPARTMENTS C
        JOIN EMPLOYEES A
             JOIN JOBS B
     ON C.DEPARTMENT_ID = A.DEPARTMENT_ID
     ON A.JOB_ID = B.JOB_ID

The only syntax that escapes conventional "restrict-project-cartesian product" is outer join. This operation is more complicated because it is not associative (both with itself and with normal join). One have to judiciously parenthesize query with outer join, at least. However, it is an exotic operation; if you are using it too often I suggest taking relational database class.

ReferenceURL : https://stackoverflow.com/questions/1599050/will-ansi-join-vs-non-ansi-join-queries-perform-differently

반응형