Ter uma ‘OR’ em uma condição INNER JOIN é uma má ideia?

Ao tentar melhorar a velocidade de uma consulta imensamente lenta (vários minutos em duas tabelas com apenas ~ 50.000 linhas cada, no SQL Server 2008, se isso importa), reduzi o problema a um OR em minha junit interna, como em:

 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 

Eu mudei isso para (o que eu espero que seja) um par equivalente de junções à esquerda, mostrado aqui:

 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 

.. e a consulta agora é executada em cerca de um segundo!

É geralmente uma má ideia colocar um OR numa condição de junit? Ou eu sou apenas azar de alguma forma no layout das minhas mesas?

   

Este tipo de JOIN não é otimizável para um HASH JOIN ou um MERGE JOIN .

Pode ser expresso como uma concatenação de dois conjuntos de resultados:

 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 

, cada um deles sendo um equijoin, no entanto, o otimizador do SQL Server não é inteligente o suficiente para vê-lo na consulta que você escreveu (embora eles sejam logicamente equivalentes).

Eu uso o seguinte código para obter resultado diferente da condição que funcionou para mim.


 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)