En essayant d'améliorer la vitesse d'une requête extrêmement lente (plusieurs minutes sur deux tables avec seulement ~ 50 000 lignes chacune, sur SQL Server 2008 si cela compte), j'ai limité le problème à un OR
dans ma jointure intérieure, comme dans:
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
J'ai changé ceci en (ce que j'espère) une paire équivalente de jointures à gauche, illustrée ici:
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
.. et la requête s'exécute maintenant dans environ une seconde!
Est-ce généralement une mauvaise idée de mettre un OR
dans une condition de jointure? Ou suis-je simplement malchanceux en quelque sorte dans la mise en page de mes tables?
Ce type de JOIN
n'est pas optimisable pour un HASH JOIN
Ou un MERGE JOIN
.
Cela peut être exprimé comme une concaténation de deux résultats:
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
Cependant, l'optimiseur de SQL Server
n'est pas assez intelligent pour le voir dans la requête que vous avez écrite (bien qu'ils soient logiquement équivalents).
J'utilise le code suivant pour obtenir un résultat différent de la condition qui a fonctionné pour moi.
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)