En essayant d'améliorer la vitesse d'une requête extrêmement lente (plusieurs minutes sur deux tables avec seulement ~ 50000 lignes chacune, sur SQL Server 2008 si cela compte), j'ai réduit le problème à une OR
jointure interne, 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é cela en (ce que j'espère est) une paire équivalente de jointures gauches, montré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 dans la disposition de mes tableaux?
Réponses:
Ce type de
JOIN
n'est pas optimisable pour aHASH JOIN
ou aMERGE JOIN
.Il peut être exprimé comme une concaténation de deux jeux de résultats:
, chacun d'entre eux étant une équi-jointure, cependant,
SQL Server
l'optimiseur de n'est pas assez intelligent pour le voir dans la requête que vous avez écrite (bien qu'ils soient logiquement équivalents).la source
ON w=x OR y=z
complètement les jointures du modèle?ON w=x OR y=z
? (Merci pour votre patience!)SQL Server
comprendre qu'une concaténation serait nécessaire. Disons que la requêteSELECT * FROM othertable WHERE parentId = 1 OR id = 2
utilisera une concaténation si les deux champs sont indexés donc théoriquement rien n'empêcherait de faire la même chose dans une boucle. LaSQL Server
construction de ce plan dépendra-t-elle de très nombreux facteurs, mais je ne l'ai jamais vu dans la vraie vie.J'utilise le code suivant pour obtenir un résultat différent de la condition qui a fonctionné pour moi.
la source
Vous pouvez utiliser UNION ALL à la place.
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
la source
UNION ALL
vous donnera des doublons par rapport auJOIN
avec uneOR
condition.union all
ce qui n'est pas correct, comme le décrit également l'article vers lequel vous créez un lien.