首先,在Orders.Order_Number,OrderDet.Order_Number和OrderDet.PatID上有索引。还有其他索引,但是这些索引在我看来很相关。
在我完成的测试中,此查询需要20到114 秒的时间来执行。
Update O
SET O.BenefitID = 1,
O.LastChangedBy = 'RH Test'
FROM Orders O
JOIN OrderDet od ON od.Order_Number = O.Order_Number
WHERE
Od.PatID = 703007
and Od.Status IN ('2', '7', '50', '51', '52', '78', '82');
如果我改为这样做,我得到的时间不到60毫秒:
SELECT ODetailID, Order_Number INTO #OrdNum FROM OrderDet
WHERE PatID = 703007
AND Status IN ('2', '7', '50', '51', '52', '78', '82');
Update Orders
SET BenefitID = 1,
LastChangedBy = 'RH Test'
WHERE Order_Number in (SELECT Order_Number from #OrdNum);
DROP TABLE #OrdNum;
有人可以告诉我为什么将OrderDet表连接到Orders时我的查询需要这么长时间吗?对我来说,加入这么长时间是没有道理的。如果我根据order_number在任一表上进行选择,则会得到200ms以下的响应。如果我使用PatID在OrderDet上选择,我将得到40ms以下的响应。通过PatId选择订单需要更长的时间-1-2秒,但该列上没有索引。我不明白为什么使用联接会花费多达114秒的时间,因为联接位于两个表中都已索引的列上。非常感谢您对此有任何帮助。
答案 0 :(得分:2)
此行为的原因是因为使用联接执行UPDATE操作时,正在更新的表被固定为嵌套循环联接的驱动表。由于“订单”表上没有直接条件,因此“表扫描”是唯一的选择。
在具有两个表的内部联接的SELECT查询中,可以将这些表切换为将具有更多限制结果的表作为驱动程序放置。这样可以提高性能。
使用临时表的另一种方法是使用子查询,该子查询无论如何都是更标准的:
Update Orders
SET BenefitID = 1,
LastChangedBy = 'RH Test'
WHERE Order_Number in
(SELECT Order_Number
FROM OrderDet
WHERE PatID = 703007
AND Status IN ('2', '7', '50', '51', '52', '78', '82'));