25

MainTable600,000 レコードを少し超えるテーブル ( ) があります。JoinTable親/子タイプの関係で、2 番目のテーブル ( ) を介してそれ自体に結合します。

SELECT   Child.ID, Parent.ID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID
JOIN     MainTable
AS       Parent
      ON Parent.ID = JoinTable.ParentID
     AND Parent.SomeOtherData = Child.SomeOtherData

すべての子レコードに親レコードがあり、JoinTable のデータが正確であることはわかっています。

このクエリを実行すると、実行に文字通り数分かかります。ただし、Left Join を使用して親に参加すると、実行に 1 秒未満かかります。

SELECT   Child.ID, Parent.ID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID
LEFT JOIN MainTable
AS       Parent
      ON Parent.ID = JoinTable.ParentID
     AND Parent.SomeOtherData = Child.SomeOtherData
WHERE    ...[some info to make sure we don't select parent records in the child dataset]...

INNER JOINanと aの結果の違いを理解していLEFT JOINます。この場合、すべての子が親を持つため、まったく同じ結果が返されます。両方のクエリを実行すると、データセットを比較できますが、それらはまったく同じです。

LEFT JOINがよりもはるかに高速に実行されるのはなぜINNER JOINですか?


UPDATEクエリプランをチェックし、内部結合を使用すると、親データセットから始まります。左結合を行う場合、子データセットから開始します。

使用するインデックスはすべて同じです。

常に子供から始めるように強制できますか? 左結合を使用するとうまくいきますが、それは間違っているように感じます。


同様の質問が以前にここで尋ねられましたが、私の質問に答えるものはないようです。

たとえば、 SQL Server の INNER JOIN と LEFT JOIN のパフォーマンスで選択された回答は、左結合は常に内部結合よりも遅いことを示しています。議論は理にかなっていますが、私が見ているものではありません。

4

2 に答える 2

2

これを試してみてください。同じ結果、異なるアプローチ:

SELECT c.ID, p.ID 
FROM
(SELECT   Child.ID, JoinTable.ParentID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID) AS c
INNER JOIN 
(SELECT   Parent.ID, JoinTable.ID
FROM     MainTable
AS       Parent
JOIN     JoinTable
      ON Parent.ID = JoinTable.ParentID
     AND Parent.SomeOtherData = Child.SomeOtherData) AS p
ON c.ParentID = p.ID

問題が解決しない場合は、cte を使用します。

;WITH cte AS
(SELECT   Child.ID, JoinTable.ParentID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID)
SELECT cte.ID, Parent.ID
FROM cte INNER JOIN 
MainTable
AS       Parent
      ON Parent.ID = cte.ParentID
     AND Parent.SomeOtherData = cte.SomeOtherData
于 2013-06-14T04:29:48.847 に答える