尽可能少地回收分区中的空闲 space
Reclaim free space in partition with as little fragmentation as possible
问题:
在 Sql server 2012 中,回收尽可能多的保留 space 并尽可能减少碎片的最佳方法是什么?
背景:
我们的 SQL 服务器 运行 磁盘空间不足 space 并且作为硬件+软件升级的一部分,我们将把数据文件移动到不同的服务器 - 出于这个原因我们想减少数据文件的大小(以防止 'reserved space' 的不必要移动。我们正在谈论 tearbytes)。我还想逐个分区执行此分区,以便能够 运行 过夜并限制对生产的影响。
我尝试过的一种方法(使用单个索引的重度消费者 table 上的每个分区):
ALTER TABLE <Tbl>
REBUILD PARTITION = <PartitionId> WITH (DATA_COMPRESSION = PAGE)
GO
--I know this is bad practice - but I need to reclaim space to speed up moving
DBCC SHRINKFILE(<PartitionName>, target_size = 10 )
GO
-- This is to mitigate the impact of shrinkfile
ALTER TABLE <Tbl>
REBUILD PARTITION = <PartitionId>
GO
--Run this in the end (and I run also between the individual tasks) to see impact on index fragmentation
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(<DbName>), OBJECT_ID(<TblName>), <IndexId>, <PartitionId>, 'SAMPLED');
GO
在测试环境中,这对某些分区产生了很好的结果(0% 的碎片化和接近 0% 'wasted' space 在保留 space 上。考虑到下一阶段正在移动数据而浪费了通过电线),但我有一个分区的情况, SHRINKFILE 显着减小了大小,但导致 99.99% 的碎片; REBUILD 解决了碎片问题,但文件组大小加倍(一半被保留 space)——这可能是预期的,因为重建从头开始创建索引。如果我之后收缩我可以回收 space,但再次得到大碎片。这可以绕圈子
我现在正尝试运行重组压缩文件组:
ALTER INDEX <IdxName> on <Tbl> REORGANIZE PARTITION = <PartitionId>
因为这应该有望在不增加数据文件的情况下修复索引碎片。
然而:
- 运行 在 99.99% 碎片索引上重组是个好主意吗?
- 结果会 comparable/inferior/superior 到 运行 重建吗?
我正在考虑的另一个选择是将分区重建为全新的文件组,但这需要处理分区架构 - 我希望该过程尽可能简单。
如何使用压缩备份数据库并将其恢复到新服务器。备份不包括未使用的 space.
这不是最佳答案,但这是我所做的,因为它最能解决我的具体情况 - 特别是 缺少任何额外的免费 space used - 所以我什至不能使用备份恢复方法; 能够以较小的(隔夜)批量执行操作。
我想post它以防有人觉得它有用。
但是 - 确保您始终拥有至少与您的数据库当前占用的空间一样多的space绝对更好,然后您可以使用更合适的解决方案,例如我标记为答案的压缩备份建议。
--This is just so that anything doesn't interract with table during the entire process.
-- reorganize is being done online; but I want the process to finish as fast as possible and
-- app logic is resilient to not seeing the table for while
exec sp_rename <tbl_orig>, <tbl>
GO
print 'starting compressing: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- this is to enable compression on the partition
ALTER TABLE <tbl>
REBUILD PARTITION = <PartitionId> WITH (DATA_COMPRESSION = PAGE)
GO
print 'Compressing done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- recaliaming all free space; potentially very bad fragmentation is possible
DBCC SHRINKFILE(<DataFile>, target_size = 10 )
GO
print 'shrinking done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- solve the fragmentation without giving up on any reclaimed space. Rebuild would use some additional space.
-- This assumes that my partitions are stored in dedicated filegroups (which is always a good idea)
ALTER INDEX <IdxName> on <tbl> REORGANIZE PARTITION = <PartitionId>
GO
print 'index reorganizing done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- see the stats
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(<DBName>), OBJECT_ID(<Tbl>), 1, <PartitionId> , 'SAMPLED');
GO
print 'DONE: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- show the table back to app logic
exec sp_rename <tbl>, <tbl_orig>
GO
您可以将分区重建到新的文件组。这将产生完美连续的页面和完美填充的文件。这通常是一种非常好的碎片整理方法。您可以将其自动化。
如您所见,通过就地重建进行碎片整理存在一些问题。您需要大量临时 space 并且您新分配的 b-tree 将被 SQL 服务器分配算法压缩成大量空闲 space 空洞。分配算法不智能。它不会试图找到大洞。如果有小洞,它很高兴将新树铺在小洞上。这就是你可能在重建后直接碎片化的原因。 (有趣的是,NTFS 也有同样的问题。如果你只是顺序写入一个 100GB 的文件,它最终可能会非常碎片化。)
我相信这个问题在 SQL 服务器社区中没有得到广泛理解。
问题: 在 Sql server 2012 中,回收尽可能多的保留 space 并尽可能减少碎片的最佳方法是什么?
背景:
我们的 SQL 服务器 运行 磁盘空间不足 space 并且作为硬件+软件升级的一部分,我们将把数据文件移动到不同的服务器 - 出于这个原因我们想减少数据文件的大小(以防止 'reserved space' 的不必要移动。我们正在谈论 tearbytes)。我还想逐个分区执行此分区,以便能够 运行 过夜并限制对生产的影响。
我尝试过的一种方法(使用单个索引的重度消费者 table 上的每个分区):
ALTER TABLE <Tbl>
REBUILD PARTITION = <PartitionId> WITH (DATA_COMPRESSION = PAGE)
GO
--I know this is bad practice - but I need to reclaim space to speed up moving
DBCC SHRINKFILE(<PartitionName>, target_size = 10 )
GO
-- This is to mitigate the impact of shrinkfile
ALTER TABLE <Tbl>
REBUILD PARTITION = <PartitionId>
GO
--Run this in the end (and I run also between the individual tasks) to see impact on index fragmentation
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(<DbName>), OBJECT_ID(<TblName>), <IndexId>, <PartitionId>, 'SAMPLED');
GO
在测试环境中,这对某些分区产生了很好的结果(0% 的碎片化和接近 0% 'wasted' space 在保留 space 上。考虑到下一阶段正在移动数据而浪费了通过电线),但我有一个分区的情况, SHRINKFILE 显着减小了大小,但导致 99.99% 的碎片; REBUILD 解决了碎片问题,但文件组大小加倍(一半被保留 space)——这可能是预期的,因为重建从头开始创建索引。如果我之后收缩我可以回收 space,但再次得到大碎片。这可以绕圈子
我现在正尝试运行重组压缩文件组:
ALTER INDEX <IdxName> on <Tbl> REORGANIZE PARTITION = <PartitionId>
因为这应该有望在不增加数据文件的情况下修复索引碎片。 然而:
- 运行 在 99.99% 碎片索引上重组是个好主意吗?
- 结果会 comparable/inferior/superior 到 运行 重建吗?
我正在考虑的另一个选择是将分区重建为全新的文件组,但这需要处理分区架构 - 我希望该过程尽可能简单。
如何使用压缩备份数据库并将其恢复到新服务器。备份不包括未使用的 space.
这不是最佳答案,但这是我所做的,因为它最能解决我的具体情况 - 特别是 缺少任何额外的免费 space used - 所以我什至不能使用备份恢复方法; 能够以较小的(隔夜)批量执行操作。
我想post它以防有人觉得它有用。
但是 - 确保您始终拥有至少与您的数据库当前占用的空间一样多的space绝对更好,然后您可以使用更合适的解决方案,例如我标记为答案的压缩备份建议。
--This is just so that anything doesn't interract with table during the entire process.
-- reorganize is being done online; but I want the process to finish as fast as possible and
-- app logic is resilient to not seeing the table for while
exec sp_rename <tbl_orig>, <tbl>
GO
print 'starting compressing: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- this is to enable compression on the partition
ALTER TABLE <tbl>
REBUILD PARTITION = <PartitionId> WITH (DATA_COMPRESSION = PAGE)
GO
print 'Compressing done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- recaliaming all free space; potentially very bad fragmentation is possible
DBCC SHRINKFILE(<DataFile>, target_size = 10 )
GO
print 'shrinking done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- solve the fragmentation without giving up on any reclaimed space. Rebuild would use some additional space.
-- This assumes that my partitions are stored in dedicated filegroups (which is always a good idea)
ALTER INDEX <IdxName> on <tbl> REORGANIZE PARTITION = <PartitionId>
GO
print 'index reorganizing done: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- see the stats
SELECT * FROM sys.dm_db_index_physical_stats
(DB_ID(<DBName>), OBJECT_ID(<Tbl>), 1, <PartitionId> , 'SAMPLED');
GO
print 'DONE: ' + CAST(GETDATE() AS NVARCHAR)
GO
-- show the table back to app logic
exec sp_rename <tbl>, <tbl_orig>
GO
您可以将分区重建到新的文件组。这将产生完美连续的页面和完美填充的文件。这通常是一种非常好的碎片整理方法。您可以将其自动化。
如您所见,通过就地重建进行碎片整理存在一些问题。您需要大量临时 space 并且您新分配的 b-tree 将被 SQL 服务器分配算法压缩成大量空闲 space 空洞。分配算法不智能。它不会试图找到大洞。如果有小洞,它很高兴将新树铺在小洞上。这就是你可能在重建后直接碎片化的原因。 (有趣的是,NTFS 也有同样的问题。如果你只是顺序写入一个 100GB 的文件,它最终可能会非常碎片化。)
我相信这个问题在 SQL 服务器社区中没有得到广泛理解。