代码之家  ›  专栏  ›  技术社区  ›  Christopher Cass

如何重复运行SQL Delete语句和收缩事务日志?

  •  0
  • Christopher Cass  · 技术社区  · 8 年前

    我有一位客户的驱动器空间不足,这完全被SQL DB和事务日志占用。不幸的是,目前我们还不能选择移动数据库和日志,所以我需要弄清楚如何从两个大型表中删除行。到目前为止,一位同事已经花了4天的时间来尝试这项工作,但还没有找到解决办法。只有13GB可用于事务日志,从这些表中删除大量数据会很快清除13GB。显然,最快的方法是将要保留的内容移动到临时表中,截断现有表,然后将其移回。不幸的是,医院内的环境非常繁忙,每小时都有成千上万的行被写入这些表格。因此,不幸的是,我们不能暂时停止写入此表以便能够截断。

    因此,我们一次从每个表中删除一个月的数据,然后收缩事务日志以再次执行此操作。我觉得应该有办法让它重复,但我不完全确定我在做什么。。。我试过:

    delete top (10000)
    from Table 1_
    where CreationDate_ < '2017-06-01' 
    
    Go
    
    delete top (10000)
    from Table2_
    where CreationDate_ < '2017-06-01' 
    
    Go
    
    dbcc shrinkfile (SQL_Log,4)
    
    Go 2
    
    Go 2
    

    这似乎会从每个表中删除10000行,然后为日志运行两次收缩文件(由于某些原因,当我们只运行两次时,它不会完全收缩到4224kb大小),但似乎不会重复。我还尝试添加()从第一条delete语句开始,在第一行“Go 2”之后结束。当我这样做时,它只会说:

    Incorrect syntax near "Go"
    

    有人知道怎么做吗?如果我们能做到这一点,我计划将delete语句的数目增加到远远大于10000的数目,并将脚本的重复次数增加到远远大于2的数目,但在我真正做到这一点之前,我需要让它工作起来。。。

    2 回复  |  直到 8 年前
        1
  •  1
  •   devlin carnate    8 年前

    您可以使用 WHILE 使用 COUNT 记录的数量。

    DECLARE @Chunk INT = 10000
    DECLARE @Date DATE = '2017-06-01'
    DECLARE @Cnt INT = SELECT COUNT(*) FROM Table 1_ WHERE CreationDate_ < @Date
    WHILE @Cnt > 0
      BEGIN
        delete top (@Chunk)
        from Table 1_
        where CreationDate_ < @Date
        SET @Cnt = @Cnt - @Chunk
      END
    //Move on to the next group
    SET @Date = '2017-07-01'
    SET @Cnt = SELECT COUNT(*) FROM Table 1_ WHERE CreationDate_ < @Date
    
    WHILE @Cnt > 0
       BEGIN
       // Your delete query
       SET @Cnt = @Cnt - @Chunk
    END
    //and so on
    
        2
  •  1
  •   David Browne - Microsoft    8 年前

    无需重复收缩日志文件。如果数据库处于简单恢复模式,则只要不在单个事务中删除太多行,日志文件就不会继续增长。清除所有行后,可以将日志文件缩小到适合环境的大小。