我有一个表变量,用于从多个表中收集记录,这些表必须稍后在我的查询中处理。
看起来有点像这样:
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,但两者都同样慢。
答案 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
如果仍然没有提供您想要的性能,您需要将它们设为临时表并对其进行适当的索引,因为表变量不允许索引。