2010-01-04 104 views
0

我的问题是我需要从表中删除大约60M记录,而不会导致使用此表的其他进程造成死锁。在这一点上,我几乎完成了使用while循环来移除记录,该循环每次只能处理大约1M个记录,但它需要整天进行。SQL Server 2005高效删除

Q1:从表中删除大量数据,使表保持在线状态并最小限度地影响其他需要在MS SQL Server 2005中使用此表的资源的最佳方式是什么?

问题2:有没有像Oracle中那样在SQL Server中实现单个行锁定(而不是表锁定)的方法? (注意回答此问题可能会回答Q1)。

A2:就像@Remus Rusanu通知我,有一种方法可以用row level locking进行删除。

回答

2

看到这个thread,原来的海报实际上做了一些测试并发布了最有效的方法。一个MVP原本是用一个选项来插入你想要保留的数据到临时表中,然后截断原始表并重新插入。

+0

我喜欢它。下一次,我必须做这样的事情不得不给这个镜头。 – 2010-01-04 21:07:42

+0

我们最初计划将记录保留到新表中。然而测试表明,从头开始重建索引的时间太长了。 – 2010-01-04 21:10:22

+0

我经常这样做,它的作用就像一个魅力。比删除大量的行要好得多。 – 2010-01-04 21:10:29

1

我最近刚刚做了类似的事情。我只是创建了一个SQL Server作业,每10分钟删除一百万行。代码如下

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 
DELETE TOP 1000000 FROM BIG_TABLE WHERE CreatedDate <= '20080630' 

说的表格有大约900万行开始。没有注意到任何重大的性能问题。

+0

因此,我写的脚本从很多表中删除数据(其中大多数表中只有一条记录),我是否需要在BEGIN TRAN之后声明一次,还是必须在脚本中使用每条删除语句? – 2010-01-04 21:15:14

+0

BEGIN TRANSACTION之前。 例如 SET TRANSACTION隔离级别READ UNCOMMITTED; 删除表A 删除表B COMMIT TRAN SET事务隔离级别YOUR_ORIGINAL_LEVEL – 2010-01-04 23:37:10

1

最有效的方法是使用分区切换,请参见Transferring Data Efficiently by Using Partition Switching。缺点是它需要提前规划分区的部署方式。

如果分区切换不可用,那么答案取决于实际的表模式。您最好发布实际模式(包括所有索引,最重要的是集群密钥定义)以及符合删除候选者的条件。

至于Q2,SQL Server自90年代中期以来就有行级锁定,我不知道你实际要问什么。

+0

如果妳downvote,解释为什么 – 2010-01-04 21:21:39

+0

SQL Server有页级锁没有行级锁。 http://download.oracle.com/docs/cd/E12151_01/doc.150/e12156/ss_oracle_compared.htm – 2010-01-04 21:24:22

+2

我建议你坚持MSDN文档的SQL Server功能,而不是Oracle的。有关SQL Server中可用的锁定模式,请参阅http://msdn.microsoft.com/en-us/library/ms189849.aspx和http://msdn.microsoft.com/en-us/library/ms189286.aspx。即使您链接的Oracle营销文档中说'SQL 7.0具有行级锁定',并且这指的是从1997年开始的SQL 7。当前版本为10.5(2008 R2),并且行级锁定已成为SQL Server的默认操作数SQL 2000(即SQL 8.0)。基于这种过时的信息做出决定不可能导致很好的解决方案。 – 2010-01-04 21:32:56