Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Sql Server-从VLT中删除列(非常大的表)_Sql Server_Tsql - Fatal编程技术网

Sql server Sql Server-从VLT中删除列(非常大的表)

Sql server Sql Server-从VLT中删除列(非常大的表),sql-server,tsql,Sql Server,Tsql,任何人都可以建议实现以下目标的最佳方法: 要求:从VLT(近400 gb)中删除5列 当我们尝试做同样的事情时,我们就面临生产上的空间问题、超时错误(通过SSM) 我们尝试在任何临时表中插入(通过关闭标识),但随后我们插入了所有近数十亿行数据,并尝试打开标识,我们面临超时错误 如果我们通过POWERSHELL执行这些操作,那么与在SSM中执行操作相比会更好 限制:生产空间有限,由于这些操作,tempdb增长迅速 请告知,从VLT中删除色谱柱的最佳方法是什么 关于我想说的是另一个表和批处理作业的组

任何人都可以建议实现以下目标的最佳方法:

要求:从VLT(近400 gb)中删除5列

当我们尝试做同样的事情时,我们就面临生产上的空间问题、超时错误(通过SSM)

我们尝试在任何临时表中插入(通过关闭标识),但随后我们插入了所有近数十亿行数据,并尝试打开标识,我们面临超时错误

如果我们通过POWERSHELL执行这些操作,那么与在SSM中执行操作相比会更好

限制:生产空间有限,由于这些操作,tempdb增长迅速

请告知,从VLT中删除色谱柱的最佳方法是什么


关于

我想说的是另一个表和批处理作业的组合

1-创建一个具有所需结构的新表。使用与旧表相同的聚集索引键

2-创建一个视图来合并旧表和新表,以便在需要时可以连续访问这两个表。要限制生产中的问题,可以将其命名为与原始表相同的名称,并将该表重命名为_Old或其他名称。显然,只在视图中包含所需的字段,而不是要删除的字段

3-交易内部:

  • 在新表中插入若干行(例如一次插入1m行或其他行)
  • 从旧表中删除,在新表上加入
这具有以下优点:低日志增长(因为您正在批处理)、低数据库增长(因为额外的行数永远不会超过您的批处理大小),并且它是增量的,因此如果速度太慢,您可以停止


坏消息是,您正在删除记录,因此一旦开始,您基本上会致力于此过程。根据需要进行多少排序,您还可以从
UNION
视图中获得tempdb压力。

我可能会考虑使用您想要的模式创建一个新的分区表,并将数据插入切换表,然后将这些表切换到新表中

如果您不太熟悉分区表和索引,我强烈推荐Kimberly Tripp的这一点

将数据插入交换机表时,可以通过执行以下操作强制执行最小日志记录:

  • 你的交换台必须是空的
  • 数据库应处于简单恢复模式
  • 您需要使用跟踪标志610,如下所示:

    DBCC TRACEON(610)

  • 您需要在表上使用tablock提示,如下所示:

    INSERT newtable WITH (TABLOCK)
    SELECT col1, col2, col3, col4 
    FROM oldtable
    WHERE col1 BETWEEN min and max
    
  • 开关表需要有一个聚集索引


  • 祝你好运。我希望这是有用的。我在SQL Server中使用VLDBs,发现分区在加载和移动数据时非常宝贵。

    不能说我有过这样大的表的经验,但如果是我,我想尝试一下,我会尝试将数据(只保留列)BCP到O/S文件中,删除该表,然后将数据BCPing回一个新表,其中只包含我需要的列。当然,这假设您在进行维护时能够使服务器离线(并且在开始之前有良好的备份)。

    。。。DROP本身是一个仅元数据的操作,只要能够获得表上的独占锁,它几乎会立即完成,这意味着使用表的所有查询都必须排空(完成)。但是,删除列并不会实际删除它们,请参见

    下一步是删除物理列(如果需要)。如果有必要,我会说“因为,根据列类型的不同,这可能不值得付出努力。”。对于可变长度列,可以通过运行来回收空间。但是,如果在未压缩的表上删除了固定大小的列(没有页面或行压缩),那么回收空间的唯一方法就是重新生成表(堆或聚集索引)。如果表已分区,您可以尝试一次脱机重建一个分区(
    altertable…REBUILD partition=N
    )。如果没有,最好的方法是在线重建,前提是您没有MAX type列(此选项)。在线重建会生成大量日志(至少是数据大小的1.5倍),但它会在内部提交,这样日志备份维护就可以回收空间,而不会导致600Gb的日志增长。如果在线重建不可行,并且表没有分区,那么我将首先重新考虑清理drop列的决定


    如果列清理是绝对必须的,并且您没有在线选择,那么您真的将面临一个痛苦的世界。进行如此大规模的操作需要数天的准备、测试,而且一点也不琐碎。您必须创建一个具有所需结构的新表,开始批量向其中传输数据,并设置一些机制来跟踪对已复制数据所做的更改,然后将这些更改应用于副本。复制所有数据并应用自复制开始以来发生的更改后,可以使用切换新表和旧表。总之,如果你能使用现成的在线选项,你会更好

    我将采用前面提到的方法之一,但有一些关键的修改。假设您使用的是SQL Server 2008,请执行以下操作:

  • 为现有非常大的表创建一个零长度副本,其中只包含要保留的列:

    select top 0 {{column subset}} into tbl_tableB from tableA
    
    还要确保将所有索引、约束等复制到新表中。标识列将由
    SELECT…INTO
    语句适当处理

  • 重命名原始表;我们将在下一步中将其替换为视图

    exec sys.sp_rename @objname = 'tableA', @newname = 'tbl_tableA'
    
  • 使用原始表名和UNION ALL创建视图:

    create view tableA
    as
    select {{column subset}} from tbl_tableA
    union all
    select {{column subset}} from tbl_tableB
    
    这将与查询数据的应用程序保持一定程度的兼容性
    BEGIN TRAN
    DELETE TOP (1000) /* or whatever batch size you want */
    FROM
        tbl_tableA
    OUTPUT (
        DELETED.{{column subset}} /* have to list each column here prefixed by DELETED. */
    )
    INTO
        tbl_tableB (
            {{column subset}} /* again list each column here */
        )
    /* Check for errors */
    /* COMMIT or ROLLBACK */
    /* rinse and repeat [n] times */
    
    drop view tableA
    drop table tbl_tableA
    exec sys.sp_rename @objname = 'tbl_tableB', @newname = 'tableA'