我有一个不太明白的特殊问题。有一个大表,我们称之为 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
返回一个空集,整个语句永远运行。我检查了估计的执行计划,它充满了表假脱机、嵌套循环和查找表具有的每个索引(很多)。不是针对子查询,而是针对删除本身。
为什么要这么做?难道它不应该只使用 ID
字段(它有)的聚集索引吗?由于 IN (...)
子句的集合为空,查询不应该在几秒钟内运行吗?
谢谢。
最佳答案
这并不能回答您的问题,但这里有另一种方法可以删除重复项,同时使用 common table expression 保留每个 Field1、Field2
的最低 id
和 row_number()
:
;with cte as (
select *
, rn = row_number() over (
partition by t.Field1, t.Field2
order by t.Id
)
from lt as t
)
--delete
select * -- preview
from cte
where rn > 1;
原始查询中的 NOLOCK
提示可能会导致您出现问题。
关于sql - 使用过滤器 WHERE Field IN (<empty set>) 时从大表中删除花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46855217/