Der*_*nch 19 sql-server shrink
我有一个有很多未使用空间的 SQL 数据库。但是,当我运行 Tasks | 收缩| 数据库和任务 | 收缩| 来自管理工作室的文件它没有释放任何空间。
不幸的是,运行它的机器的硬盘空间不足。关于为什么这个空间没有释放的任何想法。
DB 上的恢复模式也设置为简单。

这是我缩小文件时出现的未使用对话框:

我也试过通过 T-SQL 做到这一点
DBCC SHRINKDATABASE (myDatabase, 5);
我得到以下回应:
DBCC SHRINKDATABASE:数据库 ID 6 的文件 ID 1 被跳过,因为该文件没有足够的可用空间来回收。DBCC SHRINKDATABASE:数据库 ID 6 的文件 ID 2 被跳过,因为该文件没有足够的可用空间来回收。DBCC 执行完成。如果 DBCC 打印错误消息,请联系您的系统管理员。
我将做一个疯狂的猜测并说您的数据库设置为使用完全恢复。您从未根据上图备份日志(更不用说完整的日志了)。如果是这种情况,那么您的日志文件会越来越大并且无法清除,因为您没有进行备份。
如果您有房间进行完整备份,则进行日志备份并再次尝试缩小。应该工作正常。
最坏的情况(我的意思是最坏的情况,特别是如果这是一个生产数据库)是将数据库设置为简单恢复,缩小然后进行备份。即使您通常没有足够的空间进行收缩,这也应该有效。
此时请确保为数据库设置定期备份。
你可以去这里了解更多详情。
编辑:
您能告诉我们日志与数据文件的空闲百分比是多少吗?您也可以查看 sys.databases 中的 log_reuse_wait_desc。
SELECT name, log_reuse_wait_desc FROM sys.databases
Run Code Online (Sandbox Code Playgroud)
最后但同样重要的是,您是否尝试过TRUNCATEONLY收缩选项?
DBCC SHRINKFILE (Adventureworks2008R2_Log, TRUNCATEONLY)
Run Code Online (Sandbox Code Playgroud)
那么这可能有很多原因。我会提到所有可能的原因,然后定义解决问题的解决方案。
DBCC输出所提到的,您没有足够的磁盘空间来缩小数据库文件。换句话说。您尝试将页面从数据库文件移动到新创建的文件。在此期间,页面存在两次。之后 SQL Server 将删除旧的数据库文件并将新创建的文件用于生产用途。您可能需要增加磁盘空间或遵循下面提到的解决方案。可能的解决方案
最简单的解决方案是计划!检查您的数据库并尝试评估每天将插入多少数据,确定增长率。默认情况下,SQL Server 会将文件增大 10%。这对于只有 100MB 的数据库来说还不错,因为增长只有 10MB。但是,如果您的数据库变得越来越大,增长将花费许多资源和时间(100GB -> 10 GB、1TB -> 100GB 等)。以 MB 为单位定义增长因子。它不应该太小(例如 1MB),因为它会在大事务上给您的磁盘带来压力并减慢您的操作速度,但不能太大以导致巨大的写入操作(例如 10GB)。
另外定义可能升级的数据库(例如日志数据库)的增长限制。如果达到限制,事务可能会失败,但不会对日志记录数据库造成太大影响。但是,如果您的日志数据库用完所有可用磁盘空间,则可能会导致生产数据库上的事务中止/回滚。
如果您遇到问题,您的磁盘空间太小,将无法再次容纳已用的磁盘空间(例如:140GB 文件,40GB 可用空间,意味着 100GB 用于重组 -> 您至少需要额外的 100GB 可用空间用于移动操作的收缩时间),您仍然可以通过使用TRUNCATEONLY标志来获得一些空间。
DBCC SHRINKFILE (1,TRUNCATEONLY)
Run Code Online (Sandbox Code Playgroud)
这将切断所有在数据库文件末尾保留的空数据页,file_id = 1。回到我们的 140GB 示例:如果您的 140GB 数据库文件将最后写入的页面保留在 120GB 的位置,您将获得最后 20GB 几乎立即返回。这个过程非常快,因为它只是将文件结束标记移动到 120GB 的位置,并将通知您的操作系统有关可用空间的信息。
您可以使用此查询快速了解数据库文件:
SELECT *
FROM sys.sysfiles
Run Code Online (Sandbox Code Playgroud)
如果您有足够的可用磁盘空间(或者在TRUNCATEONLY对每个文件运行之后),您应该能够真正清理数据库文件并真正缩小它们。
这可以通过使用以下语句来实现:
DBCC SHRINKFILE (1);
Run Code Online (Sandbox Code Playgroud)
如果您有一个经常被写入或经常运行更大事务的数据库表,我建议定义一个目标限制。这取决于您使用该数据库的经验。通常为 5-10%(取决于数据库的大小),但至少应设置为 100-1000MB。以我们的 140GB 数据库文件(40GB 空)为例,目标大小应设置为 110GB(100GB 已用 + 10% 预留)。
您可以使用以下语句来实现这一点:
DBCC SHRINKFILE (1,112640); -- 110GB in MB
Run Code Online (Sandbox Code Playgroud)
但请注意,这可能会运行很长时间(取决于您的文件大小和您的 I/O 子系统)。由于您将在 I/O 子系统上创建更大的工作负载,因此我建议在低负载时间(可能在一夜之间)运行此类脚本。
如果你真的想清理你的数据库文件,检查所有索引和/REBUILD或REORGANIZE所有具有高碎片的索引将是一个好主意。
如果您在开发机器上或真的愿意冒险,您可以运行此语句。它将遍历数据库中的每个索引并重建它。
DECLARE @sql nvarchar(max), @sch nvarchar(max), @obj nvarchar(max), @ind nvarchar(max)
DECLARE cur CURSOR FOR
SELECT s.name, o.name, i.name
FROM sys.objects as o
INNER JOIN sys.schemas as s
ON o.schema_id = s.schema_id
INNER JOIN sys.indexes as i
ON o.object_id = i.object_id
WHERE i.type > 0
OPEN cur
FETCH NEXT FROM cur INTO @sch, @obj, @ind
WHILE @@FETCH_STATUS = 0 BEGIN
SET @sql = N'ALTER INDEX ['+@ind+'] ON ['+@sch+'].['+@obj+'] '
+ N'REBUILD PARTITION = ALL '
+ N'WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, '
+ N'ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)'
PRINT(@sql) EXEC (@sql)
FETCH NEXT FROM cur INTO @sch, @obj, @ind
END
CLOSE cur
DEALLOCATE cur
Run Code Online (Sandbox Code Playgroud)
在该过程之后,您的数据库文件可能会再次增长。但是随着每个索引中的可用空间被删除,您将能够将其缩小到更小的文件大小。
警告和附加信息
缩小数据库文件时要小心。SQL Server 提前分配文件空间是有充分理由的。磁盘分配很昂贵,尽可能少做是个好主意。如果您有一个非常灵活的数据库,它每天产生几 GB 的开销并在一段时间后释放它,那么将文件始终缩小到最小是不好的。您浪费磁盘功率来增大文件,做您的工作并再次浪费磁盘功率以再次缩小文件。在这种情况下,请注意浪费一点磁盘空间来改进您的数据操作。
希望这个长摘要可以帮助您解决问题,甚至可以帮助您为数据库制定计划。
小智 5
您还必须缩小文件以检索磁盘空间:任务 | 收缩| SQL Server Management Studio 中的文件
您需要检查选项“在释放未使用的空间之前重新组织文件”,并根据数据库的预期增长设置可用空间的百分比。
小智 5
在收缩之前,您需要检查最大表的聚集索引的页面填充度
【页面饱满度和碎片化】
重建它
[重建聚集索引]
缩小数据文件:任务| 收缩| SQL Server Management Studio 中的文件“在释放未使用的空间之前重新组织文件”
PS请注意,收缩后您将获得高度碎片化的数据库,这可能会影响性能
| 归档时间: |
|
| 查看次数: |
97835 次 |
| 最近记录: |