Al tratar de mejorar la velocidad de una consulta inmensamente lenta (varios minutos en dos tablas con solo ~ 50,000 filas cada una, en SQL Server 2008 si es importante), reduje el problema a una OR
combinación interna, como en:
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
Cambié esto a (lo que espero sea) un par equivalente de uniones izquierdas, que se muestran aquí:
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
.. y la consulta ahora se ejecuta en aproximadamente un segundo.
¿Es generalmente una mala idea poner un OR
en una condición de unión? ¿O simplemente tengo mala suerte en el diseño de mis tablas?
sql
sql-server
sql-server-2008
tsql
inner-join
ladenedge
fuente
fuente
Respuestas:
Este tipo de
JOIN
no es optimizable para aHASH JOIN
o aMERGE JOIN
.Puede expresarse como una concatenación de dos conjuntos de resultados:
, siendo cada uno de ellos un equijoin, sin embargo,
SQL Server
el optimizador no es lo suficientemente inteligente como para verlo en la consulta que escribió (aunque son lógicamente equivalentes).fuente
ON w=x OR y=z
patrón por completo.ON w=x OR y=z
? (¡Gracias por tu paciencia!)SQL Server
comprender que se necesitaría una concatenación. Digamos que la consultaSELECT * FROM othertable WHERE parentId = 1 OR id = 2
usará una concatenación si ambos campos están indexados, por lo que, en teoría, no hay nada que impida hacer lo mismo en un bucle. SiSQL Server
construiremos este plan o no, depende de muchos factores, pero nunca lo he visto construido en la vida real.Utilizo el siguiente código para obtener un resultado diferente de la condición que funcionó para mí.
fuente
En su lugar, puede utilizar UNION ALL.
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
fuente
UNION ALL
le dará duplicados en comparación conJOIN
con unaOR
condición.union all
que no es correcto como también describe el artículo al que enlaza.