INNER JOIN 조건에 'OR'이있는 것이 나쁜 생각입니까?


94

엄청나게 느린 쿼리의 속도를 높이기 위해 ( 중요한 경우 SQL Server 2008에서 각각 최대 50,000 개의 행이있는 두 테이블에서 몇 ) 문제를 다음 OR과 같이 내부 조인으로 좁혔습니다 .

SELECT mt.ID, mt.ParentID, ot.MasterID
  FROM dbo.MainTable AS mt
  INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
                                  OR ot.ID = mt.ParentID

나는 이것을 (내가 바라는 것) 동등한 왼쪽 조인 쌍으로 변경했습니다.

SELECT mt.ID, mt.ParentID,
   CASE WHEN ot1.MasterID IS NOT NULL THEN
      ot1.MasterID ELSE
      ot2.MasterID END AS MasterID
  FROM dbo.MainTable AS mt
  LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
  LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
  WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL

.. 이제 쿼리가 약 1 초 안에 실행됩니다!

OR조인 조건에 두는 것이 일반적으로 나쁜 생각 입니까? 아니면 내 테이블 레이아웃이 어떻게 든 운이 좋지 않습니까?


6
쿼리 대신 실행 계획을 보여주세요.
Blindy 2011

이상한 관계처럼 보입니다
nathan gonzalez

@Blindy : 좋은 생각입니다. 실행 계획은 Quassnoi가 아래에서 언급 한 내용을 보여줍니다. 첫 번째 쿼리는 중첩 루프를 생성하고 두 번째 쿼리는 해시 조인으로 수행됩니다.
ladenedge

답변:


114

이러한 종류 JOINHASH JOIN또는 MERGE JOIN.

두 결과 집합의 연결로 표현할 수 있습니다.

SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.parentId = m.id
UNION
SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.id = m.parentId

, 각각은 SQL Server동등 조인이지만의 옵티마이 저는 작성한 쿼리에서 볼 수있을만큼 똑똑하지 않습니다 (논리적으로 동일하지만).


3
말이 되네요, 감사합니다. 내 쿼리에 특이한 것이 있는지 또는 ON w=x OR y=z패턴의 조인을 완전히 피해야하는지 여전히 확실하지 않습니다 .
ladenedge

@ladenedge : 이러한 조인은 중첩 루프에서 테이블 스캔을 사용하여 수행됩니다. 테이블이 크면 느립니다.
Quassnoi

"이 조인"이라고 말하면 양식의 모든 조인을 의미 ON w=x OR y=z합니까? (인내 해 주셔서 감사합니다!)
ladenedge

3
@ladenedge : SQL Server연결이 필요하다는 것을 이해하는 데 도움 이 되는 추가 조건이있을 수 있습니다. SELECT * FROM othertable WHERE parentId = 1 OR id = 2두 필드가 모두 인덱싱 된 경우 쿼리 는 연결을 사용하므로 이론적으로 루프에서 동일한 작업을 수행하는 것을 방해하는 것은 없습니다. SQL Server이 계획을 실제로 구축 할지 여부 는 매우 많은 요인에 따라 다르지만 실제로 구축되는 것을 본 적이 없습니다.
Quassnoi

4

나는 나를 위해 일한 조건과 다른 결과를 얻기 위해 다음 코드를 사용합니다.


Select A.column, B.column
FROM TABLE1 A
INNER JOIN
TABLE2 B
ON A.Id = (case when (your condition) then b.Id else (something) END)

-2

대신 UNION ALL을 사용할 수 있습니다.

SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS ot


UNION ALL조건 JOIN과 비교하여 중복을 제공합니다 OR.
CodeMonkey

그 UNION이 맞을 것입니다. 자세한 내용은 다음 링크를 읽어 노동 조합 대신 -의 - 또는
Mitul Panchal

1
예, 그러나 귀하의 예제에서 귀하 union all가 링크 한 기사가 설명하는 것처럼 정확하지 않은 것으로 작성했습니다 .
CodeMonkey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.