0

我有一个庞大的数据库,它每天处理电子邮件流量。在系统中,它需要每天删除一些旧邮件:

Delete from EmailList(nolock) 
WHERE EmailId IN ( 
    SELECT EmailId 
    FROM Emails 
    WHERE EmailDate < DATEADD([days], -60, GETDATE())
)

它可以工作,但问题是:完成需要很长时间,因此日志文件变得非常大。日志文件大小每天增加超过 100GB。

我想我们可以把它改成

Delete from EmailList(nolock) 
WHERE EXISTS ( 
    SELECT EmailId 
    FROM Emails 
    WHERE (Emails.EmailId = EmailList.EmailId) AND 
        (EmailDate < DATEADD([days], -60, GETDATE()))
)

但除此之外,我们还能做些什么来提高性能。最重要的是,减少日志文件的大小?

  • EmailId 已编入索引。
4

3 回答 3

0

您是否尝试过按日期进行分区,那么您可以删除您不再感兴趣的日子的表格版本。给定一个“hugh”数据库,您肯定会运行企业版的 SQL Server(毕竟,hugh 比非常大)并且具有表分区。

于 2012-07-06T20:16:51.270 回答
0

我见过

GetDate()-60

样式语法执行得比

DATEADD([days], -60, GETDATE()))

特别是如果日期列上有索引。我和一些 DBA 同事花了很多时间试图理解为什么它会表现更好,但结果却是在布丁中。

考虑到我认为您必须删除的记录量,您可能要考虑的另一件事是分批删除,例如 1000 或 10000 条记录。这可能会加快删除过程。

于 2012-07-06T19:35:47.787 回答
0

[编辑]:

关于@TomTom 的评论:如果您有可用的 SQL Server Enterprise 版本,您应该使用 Table Partitioning

如果不是这种情况,我的原始帖子可能会有所帮助:


[原帖]

删除大量数据总是很困难的。我遇到了同样的问题,我采用了以下解决方案:

根据您的要求,这将不起作用,但也许您可以从中获得一些想法。

不要使用 1 个表,而是使用2 个具有相同架构的表。创建一个同义词(我假设您使用的是 MS SQL 服务器)指向“两个表的活动表(活动的意思是,这是您当前写入的表)。将此同义词用于应用程序中的插入,或者应用程序可以不使用同义词,而是每 x 天写入一次就更改表。

每隔 x 天,您可以截断旧的/非活动表,然后重新创建同义词以针对截断的表(如果您使用同义词解决方案),因此您每次都有效地对数据进行分区。

您必须同步活动表的切换。我通过为应用程序使用共享应用程序锁和在更改同义词时使用独占应用程序锁(== 在切换过程中阻止写入应用程序)完全自动化了这一点。

如果更改应用程序的代码不是一个选项,请考虑使用相同的原则,但不是写入同义词,而是可以创建一个视图而不是触发器(插入操作将插入“活动”分区)。触发代码需要使用类似于上面提到的 Applock 的东西进行 syhcnronize(以便在切换过程中写入)。

我的解决方案稍微复杂一些,因此我目前无法在此处发布代码,但它对于高负载应用程序没有问题,并且 swithcingt/cleanup 过程是完全自动化的。

于 2012-07-06T19:36:15.557 回答