任何人都可以建议最好的实现如下:
要求:从VLT(接近400 gb)中删除5列.
我们尝试这样做的那一刻,我们在PRODUCTION上面临空间问题,超时错误(通过SSMS)
我们试图插入任何临时表(通过保持身份关闭),但随后我们插入了所有近几十亿行数据,我们尝试切换身份,我们面临超时错误.
我们是否应该通过POWERSHELL进行这些操作,与SSMS相比更好
限制:生产空间有限,tempdb因这些操作而快速增长.
请告知,从VLT中删除列的最佳方法是什么.
问候
小智 14
我会采取已经提到的方法之一,但有一些关键的修改.假设您使用的是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
这将与查询数据的应用程序保持一定程度的兼容性.INSERTs,, UPDATEs和DELETEs将必须通过视图上的触发器来处理.这UNION ALL将防止tempdb中的压力,因为不存在排序(相对于直线UNION),并且我们一次不会存在多于一行的副本.
使用DELETE组合OUTPUT子句从原始表中批量删除数据,同时将其插入新表中:
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 */
完成DELETEs/后INSERTs,删除视图,删除原始表,重命名新表:
drop view tableA
drop table tbl_tableA
exec sys.sp_rename @objname = 'tbl_tableB', @newname = 'tableA'
这种方法的优点压倒一切的是,DELETE与INSERT在同一交易同时发生,这意味着数据将始终保持一致的状态.您可以通过更改TOP子句来增加批处理的大小,从而更好地控制事务日志的使用和阻塞.我已经在有和没有标识列的表上测试了这种精确的方法,它的效果很好.在一张非常大的桌子上,需要一段时间才能运行; 可能是几个小时到几天,但它将完成所需的结果.
Rem*_*anu 11
它ALTER TABLE ... DROP本身只是一个元数据操作,只要它能在表上获得一个独占锁,就会几乎瞬间完成,这意味着使用该表的所有查询都必须耗尽(完成).但是删除列并没有实际删除它们,请参阅引擎盖下的SQL Server表列.
如有必要,下一步是删除物理列.如果有必要,我会呼叫,因为根据列类型,它可能不值得努力.对于可变长度列,您可以通过运行来回收空间DBCC CLEANTABLE.但是,如果您在非压缩表上删除了固定大小的列(没有页面或行压缩),那么回收空间的唯一方法是重建表(堆或聚簇索引).如果表已分区,您可以尝试一次重建脱机一个分区(ALTER TABLE ... REBUILD PARTITION = N).如果没有,您的最佳镜头是在线重建,前提是您没有MAX类型列(此限制在SQL Server 2012中解除).在线重建会生成大量日志(至少是数据大小的1.5倍),但它会在内部提交,因此日志备份维护可以回收空间,并且最终不会有600Gb的日志增长.如果在线重建不可行并且表没有分区,那么我将首先重新审视清除drop column的决定.
如果列清理是绝对必须的,并且您没有在线替代方案,那么您真的有一个痛苦的世界.做这么大的操作需要几天的准备,测试,并且完全不是微不足道的.您必须创建具有所需结构的新表,开始批量传输数据并设置一些机制来跟踪对已复制数据所做的更改,然后将这些更改应用于副本.复制所有数据并应用自复制开始后发生的更改,然后您可以使用切换旧表和新表sp_rename.总而言之,你会多更好,如果你可以使用现成的现成的在线选项.