2014-02-20 3 views
0

아래 두 개의 쿼리는 동일한 결과를 제공합니다. 성능 측면에서 어느 것이 더 나은지 알고 싶습니다.SQL을 작성하는 가장 좋은 방법은

쿼리 1 :

SELECT N.* 
FROM NOTIFICATIONS N 
     JOIN NOTIFICATION_COMPANY_GROUPS NCG 
      ON (N.COMPANY_ID = NCG.COMPANY_ID 
      AND N.ID = NCG.NOTIFICATION_ID) 
     JOIN COMPANY_USER_GROUPS CUG 
      ON (N.COMPANY_ID = CUG.COMPANY_ID 
      AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID) 
     JOIN NOTIFICATION_PROPERTIES NP ON (N.COMPANY_ID = NP.COMPANY_ID) 
     JOIN COMPANY_USER_PROPERTIES CUP 
      ON (N.COMPANY_ID = CUP.COMPANY_ID 
      AND CUP.PROPERTY_ID = NP.PROPERTY_ID) 
WHERE N.COMPANY_ID = 2138 
AND CUG.COMPANY_USER_ID = 41422 
AND CUP.COMPANY_USER_ID = 41422; 

질의 2 :

SELECT N.* 
FROM NOTIFICATIONS N 
     JOIN NOTIFICATION_COMPANY_GROUPS NCG 
      ON (N.COMPANY_ID = 2138 
      AND N.COMPANY_ID = NCG.COMPANY_ID 
      AND N.ID = NCG.NOTIFICATION_ID) 
     JOIN COMPANY_USER_GROUPS CUG 
      ON (CUG.COMPANY_USER_ID = 41422 
      AND N.COMPANY_ID = CUG.COMPANY_ID 
      AND CUG.COMPANY_GROUP_ID = NCG.COMPANY_GROUP_ID) 
     JOIN NOTIFICATION_PROPERTIES NP ON (N.COMPANY_ID = NP.COMPANY_ID) 
     JOIN COMPANY_USER_PROPERTIES CUP 
      ON (CUP.COMPANY_USER_ID = 41422 
      AND N.COMPANY_ID = CUP.COMPANY_ID 
      AND CUP.PROPERTY_ID = NP.PROPERTY_ID); 
+0

쿼리 플래너는 이러한 두 가지 폼을 동등하게 처리해야합니다. 즉, * 특정 * SQL 구현에서 쿼리 계획을보고 놀라움이 있는지 확인해야합니다. 즉, 모든 (그리고 유일한) JOIN 조건은 'ON ..'비트와 'WHERE'의 나머지 부분에 모두 포함하는 것이 좋습니다. 즉, 첫 번째 형식을 권장합니다. 외부 쿼리를 읽고 이해하기 쉽고 생성, 수정 또는 통합하기가 더 쉽습니다. – user2864740

+0

왜 측정하지 않습니까? 나머지 : 가능한 한 쉽게 이해할 수 있도록 진술을 작성하십시오 (약간의 취향/사고 방식). 이렇게하면 문장이 의미 상으로 정확 해지고 유지 보수하기가 쉬워집니다. 성능 문제가 발생할 경우에만 대안을 시도하십시오. ("조기 최적화는 모든 악의 뿌리입니다", D.E.Knuth) – Ronald

답변

7

나는 성능이 동일해야 기대하지만 쿼리 계획이 있는지 확인하기 위해 EXPLAIN을 사용할 수 있습니다 같은.

그러나 첫 번째 버전은이를 작성하는 데 "적절한"방법입니다. 일반적으로 ON 절에는 조인중인 테이블과 관련된 조건 만 포함되어야하며 단일 테이블의 조건은 WHERE 절로 지정되어야합니다.

유일한 예외 테이블에 조건이 ON 절이어야 결합되는 LEFT JOIN,이다. 이것은 WHERE 절에 입력하면 명시 적으로 NULL을 확인하지 않는 한, 조인 테이블에서 일치하는 항목이없는 기본 테이블의 행에서 널 (null) 행을 필터링하기 때문입니다. 예를 들어 :

SELECT ... 
FROM T1 
LEFT JOIN T2 ON T2.T1_id = T1.id AND T2.someCol = 3 

최초 버전의

SELECT ... 
FROM T1 
LEFT JOIN T2 ON T2.T1_id = T1.id 
WHERE T2.someCol = 3 

대, T2.someCol의 시험 합류 전에 을 수행한다; 결과에는 T1의 모든 행이 포함되지만 T2에 일치하는 행이없는 행은 T2 열 모두에 대해 NULL이됩니다. 그러나 두 번째 버전은 조인이 먼저 수행 된 후 T2.someCol = 3 테스트를 수행하기 때문에 일치하지 않는 행이 없습니다. 일치하는 T2 행이 없으면 T2.someColNULL이되며이 테스트는 실패하고 행은 WHERE으로 필터링됩니다.

내부 조인의 경우 조인 전 또는 후에 비교할 때 상관 없지만 결과는 동일합니다. 쿼리 계획자는 인덱스를 최대한 활용하는 방법으로 순서를 지정해야합니다.

+1

"유일한 예외"라고 표시된 부분은 굵게 표시해야합니다. 그것은 매우 중요하며 많은 버그의 근원입니다. –

+0

왼쪽 결합에 관한 부분을 얻지 못했습니다. 이 경우 고정 기간을 단순히 이동하는 것 (예 :'cup.company_user_id = 41422')에 대해 이야기하고 있습니까? 아니면 가입 조건을 구체적으로 언급하고 있습니까? – user2864740

+0

왼쪽 조인에 대한 예제를 추가했습니다. – Barmar

관련 문제