use*_*182 17 sql-server shrink sql-server-2008-r2
我正在运行 sql 2008 r2 并且数据库在过去 3 年中运行良好且快速,直到大约 3 个月前我们在非常活跃和使用过的表上添加了 ntext 字段。现在我们开始用尽服务器空间,因为这个表的大小越来越大。
我读到了缩小,我们不想放松 db 的索引,因为它多年来一直在快速工作,而且我们不想让碎片消耗殆尽。
我们决定删除该字段及其所有值: 有没有办法删除 ntext 字段及其所有值并释放空间而不删除索引,不缩小,不损失数据库性能?
我附上 db size 查询输出,以显示过去 5 个月的大小扩展。
Kin*_*hah 14
我们决定删除该字段及其所有值:有没有办法删除 ntext 字段及其所有值并释放空间而不删除索引,不缩小,不损失数据库性能?
我建议使用(来自 BOL : )
DBCC CLEANTABLE
(
{ database_name | database_id | 0 }
, { table_name | table_id | view_name | view_id }
[ , batch_size ]
)
[ WITH NO_INFOMSGS ]
Run Code Online (Sandbox Code Playgroud)
DBCC CLEANTABLE 在删除可变长度列后回收空间。可变长度列可以是以下数据类型之一:varchar、nvarchar、varchar(max)、nvarchar(max)、varbinary、varbinary(max)、text、ntext、image、sql_variant 和 xml。删除固定长度列后,该命令不会回收空间。
!! 注意!!(使用谨慎的批量大小- 如果您的表很大,建议使用此参数):
DBCC CLEANTABLE 作为一个或多个事务运行。如果未指定批处理大小,则该命令在一个事务中处理整个表,并且在操作期间该表被独占锁定。对于一些大表,单个事务的长度和所需的日志空间可能太多。如果指定了批处理大小,该命令将在一系列事务中运行,每个事务包括指定的行数。DBCC CLEANTABLE 不能作为另一个事务内的事务运行。
此操作已完全记录。
一个简单的重现将证明这DBCC CLEANTABLE
比 SHRINKING 更好(并且不用担心碎片:-)
-- 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
Run Code Online (Sandbox Code Playgroud)
--drop the ntext column
ALTER TABLE dbo.Test DROP COLUMN col3 ;
Run Code Online (Sandbox Code Playgroud)
--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') ;
Run Code Online (Sandbox Code Playgroud)
对于大多数部分,我参考了 Paul Randall 的Inside the storage engine博客系列。
从 SQLServer 中的数据库文件中回收未使用空间的唯一方法是使用 DBCC SHRINK 命令,该命令在释放页面的数据库文件中重新分配数据,并在将它们从全局分配映射中删除后将它们从数据库文件中删除。此操作很慢,会在数据库中产生碎片,并且在处理 LOB 页面时甚至更慢,因为这些页面作为链接列表存储在数据库文件中。
由于您要删除 NTEXT 列,因此您必须等待 ghost 清理过程在缩小之前删除数据。
现在,数据库文件中有大量可用空间实际上对您没有害处,如果您有磁盘空间,备份压缩将处理文件中的可用空间。
如果您绝对想让文件更小,您可以使用数据库创建一个新文件组并将其设为默认值,然后将表移动到新文件组中,但这可能需要时间并导致停机。我使用了Bob Pusateri 在这里解释的技术,结果很好。