更快的SQL DELETE IN / IN / EXISTS需要

时间:2014-09-17 10:51:29

标签: sql sql-server tsql

我有一个表变量,用于从多个表中收集记录,这些表必须稍后在我的查询中处理。

看起来有点像这样:

DECLARE @Prices TABLE ( 
  ProductId INT, 
  Price MONEY,
  Fee INT, 
  Discount INT,
  IsSpecialPrice BIT
)

现在,在从几个表(约400K记录)收集价格相关记录后,我只需要删除几条记录。对于我有至少2条记录的产品(一条或多条IsSpecialPrice = 0,另一条IsSpecialPrice = 1),我必须删除IsSpecialPrice = 0的所有记录。

现在使用DELETE WHERE IN或DELETE WHERE EXISTS需要太长时间才能删除少量记录。所以,我在这里寻找更快的查询类型。

现在这就是我使用的:

DELETE P1
FROM @Prices P1
WHERE P1.IsSpecialPrice = 0 AND EXISTS (SELECT P2.ProductId FROM @Prices P2 WHERE P2.ProductId = P1.ProductId AND P2.IsSpecialPrice = 1)

我尝试了WHERE IN和WHERE EXISTS,但两者都同样慢。

3 个答案:

答案 0 :(得分:3)

加入怎么样?

DELETE P1
FROM @Prices P1 join (
  SELECT DISTINCT ProductId
  FROM @Prices 
  WHERE IsSpecialPrice = 1
) P2 on P1.ProductId = P2.ProductId
WHERE P1.IsSpecialPrice = 0

我在一个有500k行的表格上进行了测试,在2秒内完成了删除90k行,与无尽的exists相比,这是一个巨大的改进。

答案 1 :(得分:1)

这是您的查询:

DELETE P1
    FROM @Prices P1
    WHERE P1.IsSpecialPrice = 0 AND
          EXISTS (SELECT 1
                  FROM @Prices P2
                  WHERE P2.ProductId = P1.ProductId AND P2.IsSpecialPrice = 1
                 );

加快这一速度的正常方法是添加索引:@Prices(IsSpecialPrice)@Prices(ProductId, IsSpecialPrice)。唉,除非使用SQL Server 2014(新功能),否则无法在表变量上添加索引。

另一种方法是将其存储在显式临时表中,并在该表上添加索引。因此,对表格使用#Prices而不是@Prices

答案 2 :(得分:0)

我发现连接几乎总是更快,所以我会这样编写查询

DELETE P1
FROM @Prices P1
INNER JOIN @Prices P2 ON P2.ProductId = P1.ProductId AND P2.IsSpecialPrice = 1
WHERE P1.IsSpecialPrice = 0

如果仍然没有提供您想要的性能,您需要将它们设为临时表并对其进行适当的索引,因为表变量不允许索引。