Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在()中使用筛选器WHERE字段时从大表中删除花费的时间太长_Sql_Sql Server - Fatal编程技术网

Sql 在()中使用筛选器WHERE字段时从大表中删除花费的时间太长

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

我有一个奇怪的问题,我不太明白。有一个很大的表,我们称之为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 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,则查询是否永远运行?