Sql 在()中使用筛选器WHERE字段时从大表中删除花费的时间太长
我有一个奇怪的问题,我不太明白。有一个很大的表,我们称之为LT,有一个主键ID。我有一个DELETE语句来删除重复项,如下所示:Sql 在()中使用筛选器WHERE字段时从大表中删除花费的时间太长,sql,sql-server,Sql,Sql Server,我有一个奇怪的问题,我不太明白。有一个很大的表,我们称之为LT,有一个主键ID。我有一个DELETE语句来删除重复项,如下所示: DELETE FROM LT WHERE ID IN ( SELECT l.ID FROM ( SELECT Field1, Field2, COUNT(*) as total, MIN(ID) LowestID FROM LT (NOLOCK) WHERE Field1 = @fieldOneParam GROUP BY
DELETE FROM LT
WHERE ID IN (
SELECT l.ID FROM (
SELECT Field1, Field2, COUNT(*) as total, MIN(ID) LowestID FROM LT (NOLOCK) WHERE Field1 = @fieldOneParam
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
) a
INNER JOIN LT l (NOLOCK) on l.Field1 = a.Field1 And l.Field2 = a.Field2 And l.ID > a.LowestID
)
如果嵌套选择中有结果,则查询运行相对较快。但是,当此子查询:
SELECT l.ID FROM (
SELECT Field1, Field2, COUNT(*) as total, MIN(ID) LowestID FROM LT (NOLOCK) WHERE Field1 = @fieldOneParam
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
) a
INNER JOIN LT l (NOLOCK) on l.Field1 = a.Field1 And l.Field2 = a.Field2 And l.ID > a.LowestID
DELETE FROM LT
WHERE LT.ID > (
SELECT MIN(sub.ID)
FROM LT sub
WHERE sub.Field1 = @fieldOneParam
AND sub.Field1 = LT.Field1 AND sub.Field2 = LT.Field2
HAVING COUNT(*) > 1
)
返回一个空集,整个语句将永远运行。我检查了估计的执行计划,它充满了表假脱机、嵌套循环,并查找表中的每个索引,这些索引很多。不是针对子查询,而是针对删除本身
为什么会这样?它不应该只对它拥有的ID字段使用聚集索引吗?查询不应该在几秒钟内运行,因为在。。。子句是否为空
谢谢 这并不能回答您的问题,但这里有一种替代方法,可以删除重复项,同时使用和保持每个字段1、字段2的最低id: 原始查询中的NOLOCK提示可能是导致问题的原因
而不是对性能问题的具体回答,考虑一级相关子查询:
SELECT l.ID FROM (
SELECT Field1, Field2, COUNT(*) as total, MIN(ID) LowestID FROM LT (NOLOCK) WHERE Field1 = @fieldOneParam
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
) a
INNER JOIN LT l (NOLOCK) on l.Field1 = a.Field1 And l.Field2 = a.Field2 And l.ID > a.LowestID
DELETE FROM LT
WHERE LT.ID > (
SELECT MIN(sub.ID)
FROM LT sub
WHERE sub.Field1 = @fieldOneParam
AND sub.Field1 = LT.Field1 AND sub.Field2 = LT.Field2
HAVING COUNT(*) > 1
)
我以前也注意到过类似的行为 如果将ID保存到临时表中,则可以从临时表中ID所在的主表中删除 因此,在您的代码中,您可以将其修改为:
DECLARE @temp TABLE (ID int PRIMARY KEY)
SELECT l.ID
INTO @temp
FROM (
SELECT Field1, Field2, COUNT(*) as total, MIN(ID) LowestID FROM LT (NOLOCK) WHERE Field1 = @fieldOneParam
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
) a
INNER JOIN LT l (NOLOCK) on l.Field1 = a.Field1 And l.Field2 = a.Field2 And l.ID > a.LowestID
DELETE FROM LT
WHERE LT.ID IN (SELECT ID
FROM @temp)
如果将子查询替换为in select 1 from LT,其中1=0,则查询是否永远运行?