需要时如何缩小*正确*?

Ali*_*agg 5 sql-server shrink

我一直在阅读从停止缩小数据库文件链接的所有文章(和评论)严重地。现在。我知道缩小是不好的。

我很难弄清楚如何在实际需要时正确地做到这一点。

背景故事是我继承了这个存档数据库,其中包含一些包含 PDF 的表格,这些表格应该在 5 年后过期,但从未设置过按计划执行此操作的程序。我目前没有行数,但有几百万,大约 3TB。我想大约一半的内容将被删除并且永远不会回来。

我一直在与我们的基础设施提供商 DBA 交谈,但我发现他们给出的建议(删除、重新索引然后缩小)非常可疑。我是一名系统顾问而不是 DBA,但这次我似乎可以扮演一个:-/

Paul Randal 推荐了两种方法

1

  • 创建一个新的文件组
  • 使用 CREATE INDEX … WITH (DROP_EXISTING = ON) ON 语法将所有受影响的表和索引移动到新文件组中,以同时移动表并从中删除碎片
  • 删除您无论如何要缩小的旧文件组(如果它是主要文件组,则将其缩小)

不幸的是,我无法访问仅 SSMS 的实际服务器,无论如何这都超出了我的舒适区。我实际上不是 DBA ..

2

DBCC INDEXDEFRAG 或 ALTER INDEX … 重组。

是的,但是如何.. 有很多参数可供选择,这似乎经过优化以使大小绝对最小,而不是我所需要的,即在保持数据库尽可能健康的同时摆脱膨胀。

换句话说,我不在乎数据库是否增长了一些,它需要空间来运行,并且随着文档生产逐年增加,它会增长一些,但是每晚、每周或每月的清除现在可以控制这一点。

我还应该补充一点,我可以在晚上让这个数据库脱机而不会有太多麻烦。

Jon*_*ite 3

您的提供商 DBA 的推荐足以满足您的需求。不过,我会添加额外的检查步骤以确保您没有任何堆。当您从堆中删除记录时,空间并不总是可用,并且您将没有一个好的方法来重新组织它。如果可以,请在删除之前(或之后,根据经销商的选择)向堆添加聚集索引。如果不能,我会删除,添加聚集索引,然后将其删除。

SELECT T.name AS TableName
    , I.* FROM sys.indexes AS I
    INNER JOIN sys.tables AS T ON T.object_id = I.object_id
WHERE I.type_desc = 'HEAP'
Run Code Online (Sandbox Code Playgroud)

所以,我的步骤是:

  • 检查堆并决定行动方案。
  • 清除数据(最好是分块)、检查点或备份日志(如果适用)。
  • 碎片整理索引(如果您没有自己的脚本,Ola Hallengren 的脚本将在这里提供帮助)。首先执行此操作,以便可以将页面重新调整到正确的填充系数。否则,所使用的空间估计将被关闭,因为部分使用的页面被计为完整页面,并且您可能会有许多部分完整的页面可以合并而不会产生影响。
  • 查看当前使用的数据库文件大小。缩小到适当的大小(我喜欢在文件中保留至少 20% 的空白空间。
  • 由于收缩移动了所有内容,请再次对索引进行碎片整理。
  • 花时间评估文件增长设置,以确保它们对您的环境有意义。通常以固定大小而不是百分比增长,并确保打开即时文件初始化。

这将告诉您文件中实际使用了多少空间。

SELECT DB_NAME() AS DatabaseName
, F.name
, F.type_desc 
, F.state_desc 
, F.file_id 
, F.growth 
, F.max_size
, F.is_percent_growth
, F.physical_name
, F.size/128.0 AS CurrentSize_MB
, FILEPROPERTY(F.name, 'SpaceUsed')/128.0 AS SpaceUsed_MB
 FROM sys.database_files F
Run Code Online (Sandbox Code Playgroud)