Answers:
我们决定删除该字段及其所有值:是否可以删除ntext字段及其所有值并释放空间,而又不删除索引,不缩小索引,不降低数据库性能?
我建议使用(来自BOL :)
DBCC CLEANTABLE
(
{ database_name | database_id | 0 }
, { table_name | table_id | view_name | view_id }
[ , batch_size ]
)
[ WITH NO_INFOMSGS ]
删除可变长度列后,DBCC CLEANTABLE回收空间。可变长度列可以是以下数据类型之一:varchar,nvarchar,varchar(max),nvarchar(max),varbinary,varbinary(max),text,ntext,image,sql_variant和xml。删除固定长度的列后,该命令不会回收空间。
!! 小心!(请谨慎使用批处理大小 -如果您的表很大,建议使用此参数):
DBCC CLEANTABLE作为一个或多个事务运行。如果未指定批处理大小,则该命令将在一个事务中处理整个表,并且该表将在操作期间被独占锁定。对于某些大表,单个事务的长度和所需的日志空间可能太大。如果指定了批处理大小,则该命令将在一系列事务中运行,每个事务都包含指定的行数。DBCC CLEANTABLE不能作为另一个事务中的一个事务运行。
此操作已完全记录。
一个简单的复制品将证明它DBCC CLEANTABLE
比缩小效果更好(并且无需担心碎片问题:-)
-- clean up
drop table dbo.Test
-- create test table with ntext column that we will drop later
create table dbo.Test (
col1 int
,col2 char(25)
,col3 ntext
);
-- insert 1000 rows of test data
declare @cnt int;
set @cnt = 0;
while @cnt < 1000
begin
select @cnt = @cnt + 1;
insert dbo.Test (
col1
,col2
,col3
)
values (
@cnt
,'This is a test row # ' + CAST(@cnt as varchar(10)) + 'A'
,REPLICATE('KIN', ROUND(RAND() * @cnt, 0))
);
end
--drop the ntext column
ALTER TABLE dbo.Test DROP COLUMN col3 ;
--reclaim the space from the table
-- Note that my table is only having 1000 records, so I have not used a batch size
-- YMMV .. so find a maintenance window and you an appropriate batch size
-- TEST TEST and TEST before implementing in PROD.. so you know the outcome !!
DBCC CLEANTABLE('tempdb', 'dbo.Test') ;
对于大多数部分,我引用的是Paul Randall的“存储引擎博客”系列。
在SQLServer中从数据库文件中回收未使用空间的唯一方法是使用DBCC SHRINK命令,该命令在数据库文件释放页面中重新分配数据,并在将它们从Global Allcation映射中删除之后,将其从数据库文件中删除。此操作很慢,会在数据库中创建碎片,在处理LOB页面时会更慢,因为这些页面以链接列表的形式存储在数据库文件中。
由于要删除NTEXT列,因此必须等待虚影清理过程删除数据后再进行收缩。
现在,数据库文件中有大量可用空间实际上不会对您造成伤害,如果您有磁盘空间,则备份压缩将处理文件中的可用空间。
如果您绝对希望缩小文件的大小,可以使用数据库创建一个新的文件组并将其设置为默认文件,然后将表移到新的文件组中,但这会花费时间并导致停机。我使用了Bob Pusateri此处解释的技术,效果很好。
Since you are dropping the NTEXT column you will have to wait for the ghost cleanup process to drop the data before shrinking.
请参阅我的回答。您可以使用DBCC CLEANTABLE
释放空间。
您是否要收缩数据库文件,是因为您需要该空间用于其他数据库/非DB文件,还是因为该数据库空间不足而遇到问题?
如果是第二秒,那么您可能没有想象中那么大的问题。如果我是对的,那么您的问题就是数据库需要增长以获取新数据的额外空间时。一旦删除了该列,该列占用的所有空间将被释放,以便将新行添加到数据库的表中。这意味着需要更长的时间才能扩展数据库。同时,我将为您的数据驱动器留出一些额外的空间。大多数数据库的确会随着时间的推移而增长,并且很高兴在驱动器上拥有正常的可用空间。
我将创建一个没有违规列的镜像表,将所有数据复制到该表中,删除原始表,然后重命名镜像表。