2015-09-28 95 views
0

更新表中的值,如果数据没有在表B中的以下UPDATE语句也正是我想要它做的事:SQL Server 2012中 - 尝试使用JOIN

UPDATE [dbo].[Person] 
SET [IsUpdated] = 0 
FROM [Person] p 
WHERE p.IsUpdated = 1 
    and p.PersonID NOT IN (SELECT DISTINCT q.PersonID FROM [DeletionQueue] d, [Queue] q 
         WHERE d.fkQueueID = q.QueueID) 

然而,当我运行估计此声明的执行计划,我看到我的处理时间的70%被NOT IN SELECT语句消耗。我更愿意使用某种JOIN语句来获得相同的结果。

我试图用许多不同的方式创建声明,但最接近我已经能够复制上述声明是一个给我与我正在寻找的完全相反的结果(即如果我在Person表中有两个人,IsUpdated = 1,这两个人在队列表(QueueID)中都有一个入口,但是只有人B在DeletionQueue表(fkQueueID)中,那么Person表中的人A的记录应该只有IsUpdated更改为0)。目前,当我尝试一条JOIN语句时,人员B被更新并且人员A不被更新。

如果需要,我可以使用该语句,但在此应用程序中性能非常关键。有任何想法吗?

+0

在DeletionQueue.fkQueueID和Queue.QueueID列上有索引吗? –

+0

我在DeletionQueue.fkQueueID和Queue.QueueID列上都有索引。 – MyLilMulePepe

回答

1

您可以尝试使用NOT EXISTS代替:

UPDATE [dbo].[Person] 
    SET [IsUpdated] = 0 
FROM [Person] p 
WHERE 
    p.IsUpdated = 1 
    AND NOT EXISTS(
     SELECT 1 
     FROM [DeletionQueue] d 
     INNER JOIN [Queue] q 
      ON q.fkQueueID = q.QueueID 
     WHERE q.PersonId = p.PersonId 
    ) 

根据这一article亚伦贝特朗:

为在一定条件下不 表A中查找所有行的模式存在表B,NOT EXISTS通常是你最好的 的选择。但是,一如既往,您需要在自己的环境中测试这些模式,使用您的模式,数据和硬件,并将其与您自己的工作负载混合在一起。

+0

谢谢你的回应Felix。如果我无法找到一种不使用SELECT语句的方法,我肯定会使用NOT EXISTS而不是NOT IN,因为这将有助于提高性能。但是,我的70%的时间仍在SELECT查询上。 – MyLilMulePepe

+0

你的意思是'NOT IN'中的'SELECT'查询吗?尝试删除“DISTINCT”子句。 –

+0

其实,我的意思是在'NOT EXISTS'中的代码片段中的'SELECT'查询。我仍然认为这将是我最好的选择。再次感谢。 – MyLilMulePepe