【问题标题】:SQL Server - Delete Rows EfficientlySQL Server - 有效地删除行
【发布时间】:2017-09-16 07:53:11
【问题描述】:

我在 SQL Server 2012 标准数据库中有以下 PipelineArchives 表(恢复模型为“简单”):

该表在Body 列中保存归档数据。这随着时间的推移而增长,现在包含 11,914 行,总共 53gb 的数据。我想执行一个查询,删除在当前日期 - 3 个月之前具有 CreatedOn 值的所有行。

我试着跑了

DELETE FROM PipelineArchives 
WHERE CreatedOn < MyDate

MyDate 条件产生几行时,查询将在几秒钟内从 SSMS 执行正常。但是,将日期增加到 229 行需要 30 秒。

有没有更有效的方法来删除行?

【问题讨论】:

  • 抱歉 - 什么是 EAV?
  • 将 > 当前日期 - 3 个月的行复制到另一个表中。删除原表,重命名....

标签: sql sql-server tsql


【解决方案1】:

您可以增加删除,它将防止表上的锁定并允许其他事务运行。它将使用更多的 CPU 和内存,但更熟练。

DECLARE @archiveId BIGINT

WHILE (SELECT COUNT(*) FROM PipelineArchives WHERE CreatedOn < MyDate) > 0
BEGIN

   SELECT TOP 1 @archiveId = PipelineArchiveId
   FROM PipelineArchives 
   WHERE CreatedOn < MyDate

   DELETE PipelineArchives 
   WHERE PipelineArchiveId = @archiveId

END

【讨论】:

  • 每次计算条目的效率低于检查条件是否存在行 (WHERE EXISTS(SELECT ...))。另外:DELETE TOP (1) ... 而不是先选择 ID。
  • TT 你是对的,你真的不想每次都计算生产表。然而,逻辑是熟练的方法。您可以更改循环并使用 @counter 变量。
【解决方案2】:

有时正确的做法是反其道而行之。

创建一个新表 PipelineArchivesNew 并从 PipelilneArchives where CreatedOn &gt;= MyDate 复制行。在新表中获得所需的所有数据后,将 PipelineArchives 重命名为 PipelineArchivesOld 并将 PipelineArchivesNew 重命名为 PipelineArchives。然后删除PipelineArchivesOld

这对您来说可能是也可能不是一个好的解决方案,具体取决于系统的设置方式。

【讨论】:

  • 非常糟糕的主意。如果这是您的生产表。你对表的索引、触发器或安全权限呢?这些都不会被复制,您必须重新设置。
【解决方案3】:

你也可以尝试不使用变量:

SET ROWCOUNT 5

WHILE (SELECT COUNT(*) FROM PipelineArchives WHERE CreatedOn < MyDate) > 0
BEGIN
   DELETE PipelineArchives 
   FROM PipelineArchives 
   WHERE CreatedOn < MyDate
END

SET ROWCOUNT 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2017-11-16
    相关资源
    最近更新 更多