这是一次冒险。我从位于my previous question的循环重复查询开始,但每个循环将覆盖所有 1700万条记录,意味着需要数周(仅运行{{ 1}}使用MSSQL 2005获取我的服务器4:30分钟。我从这个网站和post发现了信息。
已经到达下面的查询。问题是,对于任何类型的性能,这是在1700万条记录上运行的正确类型的查询吗?如果不是,那是什么?
SQL QUERY:
*select count * from MyTable*
答案 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