如何在具有多个表的SQL Server中执行数据归档?

如何在具有多个表的SQL Server中执行数据归档?,sql,sql-server,ssms,Sql,Sql Server,Ssms,假设我有一个包含许多表的数据库。我想对某些表执行数据归档,即创建一个与新表具有相同结构(相同的约束、索引、列、触发器等)的表,并将特定数据从旧表插入到新表中 例如,当前表包含2008-2017年的数据,我只想将2010-2017年的数据移动到新表中。然后,我可以删除旧表,并使用与旧表类似的命名约定重命名新表 我应该如何处理这个问题?对于您所讨论的克隆重命名丢弃逻辑,基本原理非常简单。实际上,这是一个好主意的唯一时间是,如果您有一个包含大量数据的表,而您负担不起停机时间或阻塞,并且您只计划执行这一

假设我有一个包含许多表的数据库。我想对某些表执行数据归档,即创建一个与新表具有相同结构(相同的约束、索引、列、触发器等)的表,并将特定数据从旧表插入到新表中

例如,当前表包含2008-2017年的数据,我只想将2010-2017年的数据移动到新表中。然后,我可以删除旧表,并使用与旧表类似的命名约定重命名新表


我应该如何处理这个问题?

对于您所讨论的克隆重命名丢弃逻辑,基本原理非常简单。实际上,这是一个好主意的唯一时间是,如果您有一个包含大量数据的表,而您负担不起停机时间或阻塞,并且您只计划执行这一次。该过程如下所示:

  • 将原始表中的所有数据插入克隆表
  • 在单个事务中,
    sp\u将原始表从(例如)
    myTable
    重命名为
    myTable\u OLD
    (只是为了将其与实际表区分开来)。然后
    sp\u重命名
    克隆表从(例如)
    myTable\u克隆
    myTable
  • 当你高兴的时候,放下我的桌子,一切都按照你的意愿进行了。如果它不能按您所希望的方式工作,只需重新命名对象即可
  • 如果你走这条路,需要考虑几个因素

    • 标识列:如果您的表上有任何标识,则必须使用
      Identity\u insert on
      然后重新设置标识的种子,以便在旧标识停止的位置拾取
    • 当你这样做的时候,你有没有把桌子挡住的奢侈?通常,如果您需要执行这类操作,答案是否定的。我发现效果很好的方法是使用
      (nolock)
      插入我需要的所有行,或者不管您如何执行,都可以减轻从原始表中选择的影响。然后,在我移动了99%的数据之后,我将打开一个事务,阻塞原始表,只插入自数据移动以来进入的新数据,然后执行
      sp_rename
      操作
      • 这样,您就不会对大部分数据移动锁定任何内容,而只会在原始insert和
        sp_rename
      • 如何确定“自开始”中的内容将取决于表的结构。如果您有一个标识或一个日期戳列,您可能只需要选择在您移动的字段的最大值之后的行。如果你的桌子上没有一些你可以轻松勾住的东西,你可能需要发挥创造力
    备选方案 我想到了另外两个选择:

    表分区: 这将在多个分区中分割一个表(可以像管理单个表一样进行管理)。例如,您可以按年份对数据进行分区,然后当您想要清除后面年份的数据时,您可以将该分区“切换”到一个特殊的表中,然后截断该表。所有这些操作都只是元数据,所以它们的速度非常快。这对于删除和所有令人讨厌的事务日志记录都不可行的海量数据也非常有效

    表分区的缺点是设置和管理起来有点麻烦

    批量删除: 如果您的数据不是太大,您可以在数据的末尾执行批处理删除。如果您能找到一种方法来获取用于删除的聚集索引,那么它们应该是相当轻量级的。只要你积累数据的速度不超过你处理数据的速度,这类事情的好处就是你只需半连续地运行它,它只会在你数据的尾端逐渐消失

    快照隔离:
    如果删除导致阻塞过多,还可以设置快照隔离之类的设置,它基本上将行的历史版本存储在
    tempdb
    中。任何设置隔离级别读取提交快照的查询都将读取这些更改前的行,而不是在“real”表上争用锁。然后,您可以对hearts内容进行批量删除,并知道任何命中表的查询都不会被删除(或任何其他DML操作)阻止,因为它们将读取删除前快照,或者读取删除后快照。他们不会等待进程内删除来确定它是提交还是回滚。不幸的是,这也并非没有缺点。对于大型数据集,它可能会给tempdb带来很大的负担,也可能有点像一个黑匣子。它还需要DBA的认可。

    右键单击数据库并使用生成脚本。单击最后一个屏幕上的Advanced(高级)以包括触发器、约束等。更详细地说,我目前正在使用此方法,但正确的数据归档过程是什么?我是删除旧表,保留新表并将其重命名为旧表名,还是只保留它?有不同的方法。大多数情况下,您希望插入到新表(col1、col2等)中,从旧表中选择col1、col2等,其中dateField>='2010-01-01',因此最终结果是您删除了后面两年的数据?是的,例如,我不想保留早于2015年的数据。详细信息非常丰富。谢谢但我想既然我已经完成了这个删除和重命名方法的一半,。我会坚持下去。只是一个问题,我能这样做吗。我使用insert into TableNew…从表中选择要保留的数据。然后我是否删除该表,然后继续将主键、索引、触发器等重命名为表中的主键、索引、触发器等?正如我所知,你不能有类似的命名约定