我在一个包含50万条记录的表上运行此查询,其中包含大约7个字段:
delete from qvalues where rid not in
(
select min(rid) from qvalues
group by name,compound,rowid
having COUNT(*)>1)
and rid not in (select min(rid) from qvalues
group by name,compound,rowid
having COUNT(*)=1);
为什么这么长时间?
我该怎么做才能优化它?
即时运行sql server 2008
答案 0 :(得分:2)
最好的办法是查看执行计划,看看花费的时间最长。我首先将两个not in
查询减少为一个:
delete
from qvalues
where rid not in
(
select min(rid)
from qvalues
group by name, compound, rowid
having count(1) >= 1
)
您可能还想考虑在name
,compound
和rowid
答案 1 :(得分:1)
不知道所涉及的实际数据,我可以给出一些一般性建议:分别运行每个子查询。
另外,我读错了,或者你是否删除了此表中的所有条目(如果删除是唯一的)?
答案 2 :(得分:1)
1 - 使用批处理。这可让您恢复,并让您了解进度。举个例子:
DECLARE @MSG Varchar(max)
WHILE 1=1
BEGIN
DELETE TOP (100000) qvalues
FROM qvalues WITH (TABLOCKX)
<logic here>
IF @@ROWCOUNT < 100000 BREAK
SET @Msg = 'Deleted another 10 Million'
SET @Msg = @Msg + ' ' +CONVERT(varchar(20),GETDATE(),101)+' '+CONVERT(varchar(20),GETDATE(),108)
RAISERROR(@Msg, 0, 1) WITH NOWAIT
END
请注意,我还添加了一个WITH (TABLOCKX)
提示,它会锁定表锁并消除行级锁定。它会导致并发读取问题,但希望您在删除时没有其他任何查询该表的内容。
2 - 修复你的逻辑如果没有更好地了解你的表结构,这是不可能的,但有些选项是:
- 使用要比较的值实现表格并进行连接。如果删除足够大,则可以在连接字段的临时表上创建聚簇索引。我用了很多东西并取得了巨大的成功。
- 如果您希望删除大部分记录,SELECT INTO
新表并删除旧表。这是一个记录最少的操作,并且在SQL Server 2008上运行得非常快,而删除则需要记录每行的值。
- 删除所有索引,但是您用于选择的内容和聚簇索引。如果聚类索引是查询的相关群集,则保留聚簇索引通常可以删除此类型。
答案 3 :(得分:1)
除了考虑批处理和索引之外,您还可以重写查询本身以删除子查询并提高效率。
;WITH cte As
(
SELECT ROW_NUMBER() OVER (PARTITION BY name, compound, rowid ORDER BY rid) AS RN
FROM qvalues
)
DELETE FROM cte WHERE RN > 1
每组可能会有多少重复?如果很多,可以更快地插入记录以保存到新表中,然后删除并重命名。
答案 4 :(得分:0)
首先想到:
delete from qvalues where rid not in
(
select min(rid) from qvalues
group by name,compound,rowid
having COUNT(*)>1
UNION
select min(rid) from qvalues
group by name,compound,rowid
having COUNT(*)=1);
也许这也是一个好主意,确保sql-server知道你正在做一个“不相关的子选择”(因为“相关的子选择”需要更长的时间):
delete from qvalues a where a.rid not in
(
select min(b.rid) from qvalues b
group by b.name,b.compound,b.rowid
having COUNT(*)>1
UNION
select min(c.rid) from qvalues c
group by c.name,c.compound,c.rowid
having COUNT(*)=1);
当然你应该考虑使用索引(尤其是关于rid,还要关于name,compound,rowid)
我的SQL没有经过测试 - 我希望你能够了解我想要展示的内容。
PS:你的sql需要大量的计算(特别是HAVING
条款),你能否尝试为你的问题找到另一种解决方案?
答案 5 :(得分:0)
您的机器设置是什么,您是否有足够的内存,在查询运行时(CPU,内存,磁盘IO),您在哪里可以看到最大的利用率?