删除表字段后声明磁盘空间


16

我正在运行sql 2008 r2,并且数据库在过去3年中运行良好且运行迅速,直到大约3个月前,我们在非常活跃和使用过的表上添加了ntext字段。现在,由于此表的巨大扩展空间,我们开始摆脱服务器空间。

我读到收缩,我们不想失去db的索引,因为它的工作速度已经快了很多年了,我们也不想让碎片化花费。

我们决定删除该字段及其所有值: 是否可以删除ntext字段及其所有值并释放空间,而又不删除索引,不缩小索引,不降低数据库性能?

我附上数据库大小查询输出,以显示最近5个月的大小扩展。

在此处输入图片说明

Answers:


12

我们决定删除该字段及其所有值:是否可以删除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') ;

在此处输入图片说明

在此处输入图片说明


执行DBCC CLEANTABLE命令后,如果表有一个索引,则需要重新构建聚簇索引,以获取空间。已重新建立YourTable上的ALTER INDEX IndexName;
TA先生

6

对于大多数部分,我引用的是Paul Randall的“存储引擎博客”系列。

在SQLServer中从数据库文件中回收未使用空间的唯一方法是使用DBCC SHRINK命令,该命令在数据库文件释放页面中重新分配数据,并在将它们从Global Allcation映射中删除之后,将其从数据库文件中删除。此操作很慢,会在数据库中创建碎片,在处理LOB页面时会更慢,因为这些页面以链接列表的形式存储在数据库文件中。

由于要删除NTEXT列,因此必须等待虚影清理过程删除数据后再进行收缩。

现在,数据库文件中有大量可用空间实际上不会对您造成伤害,如果您有磁盘空间,则备份压缩将处理文件中的可用空间。

如果您绝对希望缩小文件的大小,可以使用数据库创建一个新的文件组并将其设置为默认文件,然后将表移到新的文件组中,但这会花费时间并导致停机。我使用了Bob Pusateri此处解释的技术,效果很好。


幽灵清理过程是否还会减少空间或缩小?
user1021182 2015年

你将永远有萎缩,清理过程只清空分配的页面,但不会从数据库文件删除
Spörri

1
@Spörri 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释放空间。
Kin Shah 2015年

4

您是否要收缩数据库文件,是因为您需要该空间用于其他数据库/非DB文件,还是因为该数据库空间不足而遇到问题?

如果是第二秒,那么您可能没有想象中那么大的问题。如果我是对的,那么您的问题就是数据库需要增长以获取新数据的额外空间时。一旦删除了该列,该列占用的所有空间将被释放,以便将新行添加到数据库的表中。这意味着需要更长的时间才能扩展数据库。同时,我将为您的数据驱动器留出一些额外的空间。大多数数据库的确会随着时间的推移而增长,并且很高兴在驱动器上拥有正常的可用空间。


我们只剩下10gb的磁盘空间,而且几天后就会用完。我们已经删除了我们可以从服务器中删除的所有内容,并使用了清理操作并停止了Windows更新并全部删除了它们并清理了winsxs,我们现在必须减小db文件的大小
user1021182 2015年

同样,请记住,一旦删除了多余的列,则在填充释放的新空间时,数据库增长将停止一段时间。如果您的数据库在此之后仍在增长,那么您将绝对需要数据库的额外磁盘空间。可能将新驱动器添加到服务器。
肯尼斯·费舍尔

0

我将创建一个没有违规列的镜像表,将所有数据复制到该表中,删除原始表,然后重命名镜像表。


在这种情况下,还需要准备所有索引
user1021182 2015年

是的,也将需要删除并重新创建影响表的所有索引。...也适用于引用该表的其他对象,例如:触发器
ardochhigh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.