Ao tentar melhorar a velocidade de uma consulta extremamente lenta (vários minutos em duas tabelas com apenas ~ 50.000 linhas cada, no SQL Server 2008 se for importante), reduzi o problema a um OR
em minha junção 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
Mudei isso para (o que 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
em uma condição de junção? Ou estou apenas com azar de alguma forma no layout das minhas mesas?
sql
sql-server
sql-server-2008
tsql
inner-join
carregado
fonte
fonte
Respostas:
Este tipo de
JOIN
não é otimizado para aHASH JOIN
ou aMERGE JOIN
.Pode ser expresso como uma concatenação de dois conjuntos de resultados:
, cada um deles sendo um equijoin, no entanto,
SQL Server
o otimizador de não é inteligente o suficiente para ver isso na consulta que você escreveu (embora eles sejam logicamente equivalentes).fonte
ON w=x OR y=z
totalmente as junções do padrão.ON w=x OR y=z
? (Obrigado por sua paciência!)SQL Server
entender que uma concatenação seria necessária. Digamos que a consultaSELECT * FROM othertable WHERE parentId = 1 OR id = 2
usará uma concatenação se os dois campos forem indexados, portanto, teoricamente, não há nada que impeça de fazer a mesma coisa em um loop. SeSQL Server
vai construir esse plano de verdade ou não, depende de muitos fatores, mas nunca vi isso ser construído na vida real.Eu uso o seguinte código para obter resultados diferentes da condição que funcionou para mim.
fonte
Você pode usar UNION ALL em seu lugar.
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
fonte
UNION ALL
fornecerá duplicatas em comparação comJOIN
com umaOR
condição.union all
que não é correto, como o artigo para o qual o link também descreve.