SQL复制删除数百万行的查询以提高性能

时间:2008-10-02 13:41:59

标签: sql sql-server duplicate-data sql-delete

这是一次冒险。我从位于my previous question的循环重复查询开始,但每个循环将覆盖所有 1700万条记录意味着需要数周(仅运行{{ 1}}使用MSSQL 2005获取我的服务器4:30分钟。我从这个网站和post发现了信息。

已经到达下面的查询。问题是,对于任何类型的性能,这是在1700万条记录上运行的正确类型的查询吗?如果不是,那是什么?

SQL QUERY:

*select count * from MyTable*

11 个答案:

答案 0 :(得分:6)

查看QueryPlan会有所帮助。

这可行吗?

SELECT m.*
into #temp
FROM tl_acxiomimport.dbo.tblacxiomlistings m 
inner join (SELECT RecordID, 
                   Rank() over (Partition BY BusinessName, 
                                             latitude,  
                                             longitude,            
                                             Phone  
                                ORDER BY webaddress DESC,  
                                         caption1 DESC,  
                                         caption2 DESC ) AS Rank
              FROM tl_acxiomimport.dbo.tblacxiomlistings
           ) al on (al.RecordID = m.RecordID and al.Rank = 1)

truncate table tl_acxiomimport.dbo.tblacxiomlistings

insert into tl_acxiomimport.dbo.tblacxiomlistings
     select * from #temp

答案 1 :(得分:2)

您的数据库,服务器,存储或其某些组合可能会出现问题。 4:30选择计数*似乎非常高。

运行DBCC_SHOWCONTIG以查看表格的碎片程度,这可能会导致对大小的表格产生重大影响。

此外,要添加RyanKeeter的评论,请运行show plan,如果有任何表扫描,请在该表上为PK字段创建索引。

答案 2 :(得分:2)

这样做不会更简单:

DELETE tl_acxiomimport.dbo.tblacxiomlistings
WHERE RecordID in 
(SELECT RecordID
   FROM (
        SELECT RecordID,
            Rank() over (Partition BY BusinessName,
                                  latitude,
                                  longitude,
                                  Phone
                         ORDER BY webaddress DESC,
                                  caption1 DESC,
                                  caption2 DESC) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        )
  WHERE Rank > 1
  )

答案 3 :(得分:1)

在查询分析器中运行:

SET SHOWPLAN_TEXT ON

然后请求查询分析器运行您的查询。 SQL Server将生成查询计划并将其放入结果集中,而不是运行查询。

向我们展示查询计划。

答案 4 :(得分:1)

1700万条记录什么都没有。如果需要4:30才能进行选择计数(*),那么就会出现严重的问题,可能与服务器内存不足或处理器老旧有关。

为了提高性能,请修理机器。将其泵送至2GB。 RAM现在非常便宜,其成本远远低于你的时间。

当查询进行时,处理器或磁盘是否会发生颠簸?如果没有,那么有些东西阻止了这些电话。在这种情况下,您可以考虑将数据库置于单用户模式中,以确定运行清理所需的时间。

答案 5 :(得分:1)

所以你要删除所有未排名第一的记录?可能值得将连接与前1个子查询进行比较(这可能也适用于2000年,因为排名仅为2005及以上)

您是否需要在一次操作中删除所有重复项?我假设您正在执行某种内务管理任务,您可能可以分段执行。

基本上创建一个循环所有记录的游标(脏读)并删除每个记录的欺骗。总体来说它会慢得多,但每次操作都会相对最小。然后你的家务管理成为一个持续的后台任务而不是每晚一次。

答案 6 :(得分:1)

首先选择临时表的建议是最好的选择。你也可以使用类似的东西:

set rowcount 1000

在运行删除之前。删除1000行后,它将停止运行。然后反复运行,直到删除0条记录。

答案 7 :(得分:1)

如果我正确理解你的查询与

相同
DELETE tl_acxiomimport.dbo.tblacxiomlistings
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

我认为应该运行得更快,我倾向于避免在可能的情况下使用“IN”子句来支持JOIN。

您可以通过简单地在FROM部分调用SELECT *SELECT COUNT(*)来安全地测试速度和结果,例如

SELECT *
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

这是我更喜欢JOIN方法的另一个原因 我希望有帮助

答案 8 :(得分:0)

这看起来很好,但您可以考虑将数据选择到临时表中并在删除语句中使用它。我注意到这样做会带来巨大的性能提升,而不是在一个查询中完成所有操作。

答案 9 :(得分:0)

请记住,在进行大型删除时,最好先备份一个好的备份。(我通常也会将删除的记录复制到另一个表中以防万一,我需要立即恢复它们。)

答案 10 :(得分:-1)

除了建议使用truncate之外,我还有幸使用此模板从表中删除大量行。我不记得了,但我认为使用该事务有助于保持日志文件的增长 - 可能是另一个原因 - 不确定。在执行以下操作之前,我通常会将事务日志记录方法切换为简单:

SET ROWCOUNT 5000
WHILE 1 = 1
BEGIN
    begin tran
            DELETE FROM ??? WHERE ???
            IF @@rowcount = 0
            BEGIN
               COMMIT
               BREAK
            END
    COMMIT
END
SET ROWCOUNT 0