In trying to improve the speed of an immensely slow query (several minutes on two tables with only ~50,000 rows each, on SQL Server 2008 if it matters), I narrowed down the problem to an OR
in my inner join, as in:
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
I changed this to (what I hope is) an equivalent pair of left joins, shown here:
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
.. and the query now runs in about a second!
Is it generally a bad idea to put an OR
in a join condition? Or am I just unlucky somehow in the layout of my tables?
The following recommendations will help you in your SQL tuning process.
You'll find 3 sections below:
CREATE INDEX othertable_idx_id ON dbo.OtherTable (ID);
CREATE INDEX othertable_idx_parentid ON dbo.OtherTable (ParentID);
SELECT
mt_id,
mt_parentid,
ot_masterid
FROM
((SELECT
mt.ID AS mt_id,
mt.ParentID AS mt_parentid,
ot.MasterID AS ot_masterid
FROM
dbo.MainTable AS mt
INNER JOIN
dbo.OtherTable AS ot
ON ot.ID = mt.ParentID)
UNION
(
SELECT
mt.ID AS mt_id,
mt.ParentID AS mt_parentid,
ot.MasterID AS ot_masterid
FROM
dbo.MainTable AS mt
INNER JOIN
dbo.OtherTable AS ot
ON ot.ParentID = mt.ID
)
) AS union1