我必须编写一个查询来根据另外两个不同表中的记录更新表中的所有记录。我写了以下三个查询迭代,我认为第三个是最有效的,第一个是最差的。我只是想得到第二个意见,并找出我是否能比下面的第三个版本做得更好:
P.S:第一个不是真正有效的SQL查询,而是我计划如何查询数据库的伪代码。
SELECT AccountID,Label FROM QueueTable
For each record in query above
SELECT FeedbackID FROM FeedbackIndexed WHERE FeedbackIndexed.Label = QueueTable.Label
AND FeedbackIndexed.AccountID = QueueTable.AccountID
UPDATE FeedbackTable SET Flag = 1 WHERE FeedbackID=@FeedbackID
next
---------------------------------------------------------------------------------------------------------------------
UPDATE FeedbackTable
SET Flag = 1
WHERE FeedbackID IN(SELECT DISTINCT FeedbackID
FROM FeedbackIndexed,
QueueTable
WHERE FeedbackIndexed.Label = QueueTable.Label
AND FeedbackIndexed.AccountID = QueueTable.AccountID)
----------------------------------------------------------------------------------------------------------------------
UPDATE FeedbackTable
SET FeedbackTable.Flag = 1
FROM FeedbackTable
INNER JOIN FeedbackIndexed
ON FeedbackIndexed.FeedbackID = FeedbackTable.FeedbackID
INNER JOIN QueueTable WITH (TABLOCK)
ON FeedbackIndexed.Label = QueueTable.Label
AND FeedbackIndexed.AccountID = QueueTable.AccountID
(I used table lock on QueueTable because at the end of this query i want to drop all records from the que and don't want other parts of the app adding more records to this table while the query above runs, is that right way to do this?)
答案 0 :(得分:5)
你的第二个和第三个例子都是有效的。以下是几点:
DISTINCT
只会增加开销。执行IN
操作时,SQL通常不会执行完整的连接操作,并在找到匹配后立即退出。它也不返回所有行,只返回true / false是否匹配给定值。 IN
可能会产生一个更优化的连接运算符(半连接与连接),因为您明确声明您对子查询的输出不感兴趣,只是是否存在是返回的记录。 EXISTS
子句。虽然常见的误解是IN
效率低于EXISTS
(它们实际上在大多数情况下实现相同的查询)IN
在处理空值时可能会产生意外结果。 EXISTS
版本看起来像这样:
UPDATE FT
SET Flag = 1
FROM FeedbackTable
WHERE EXISTS(SELECT *
FROM FeedbackIndexed FI
INNER JOIN QueueTable QT
ON FI.Label = QT.Label
AND FI.AccountID = QT.AccountID
WHERE FeedbackID = FT.feedbackID)
基础查询计划可能与您的IN
示例完全相同(删除冗余DISTINCT
后),它可能会产生与第3个示例相同的查询计划,但总是很好知道解决问题的不同方法。
还有几点。
TABLOCK
将在查询完成时释放,除非您将查询和查询包装在显式事务中删除已处理的记录。我非常确定你也想在这里添加HOLDLOCK
。 HOLDLOCK
将在交易期间持有锁。 TABLOCK
将实现共享锁,这可能会导致竞争条件。如果这是一个问题,请考虑使用TABLOCKX
。 我希望这会有所帮助。