55

我有一个大小接近 1.9Gb 的数据库,而 MSDE2000 不允许超过 2.0Gb 的数据库

我需要缩小这个数据库(以及在不同客户端位置的许多其他数据库)。

我发现并删除了许多被认为不需要的 1000 条记录中的 100 条:这些记录占数据库中一些主要(最大)表的很大一部分。因此,假设现在应该可以检索到很多空间是合理的。

所以现在我需要缩小数据库来解决丢失的记录。

  • 我执行DBCC ShrinkDatabase('MyDB')……没有效果。
  • 我已经尝试过 MSSMS 中提供的各种收缩工具......仍然没有效果。
  • 我已经备份了数据库并恢复了它......仍然没有效果。

还是 1.9Gb

为什么?

无论我最终找到什么过程,都需要在客户端机器上重播,除了 OSql 或类似的东西之外什么都不能访问。

4

16 回答 16

105
ALTER DATABASE MyDatabase SET RECOVERY SIMPLE

GO

DBCC SHRINKFILE (MyDatabase_Log, 5)

GO

ALTER DATABASE MyDatabase SET RECOVERY FULL

GO
于 2009-08-18T15:30:10.797 回答
11

这可能看起来很奇怪,但它对我有用,我已经编写了一个 C# 程序来自动化它。

第 1 步:截断事务日志(仅备份事务日志,打开删除不活动事务的选项)

第 2 步:运行数据库收缩,将所有页面移动到文件的开头

第 3 步:再次截断事务日志,因为第 2 步添加了日志条目

第 4 步:再次运行数据库收缩。

我使用 SQL DMO 库的精简代码如下:

SQLDatabase.TransactionLog.Truncate();
SQLDatabase.Shrink(5, SQLDMO.SQLDMO_SHRINK_TYPE.SQLDMOShrink_NoTruncate);
SQLDatabase.TransactionLog.Truncate();
SQLDatabase.Shrink(5, SQLDMO.SQLDMO_SHRINK_TYPE.SQLDMOShrink_Default);
于 2009-01-13T15:16:15.353 回答
9

这是一个老问题,但我只是碰巧遇到了它。

已经给出了真正简短而正确的答案,并且获得了最多的选票。这就是缩小事务日志的方式,这可能是 OP 的问题。并且当事务日志变得失控时,通常需要将其缩回,但应注意防止将来出现日志失控的情况。dba.se上的这个问题解释了这一点。基本上 - 首先不要让它通过适当的恢复模型、事务日志维护、事务管理等变得那么大。

但是当我阅读这个关于缩小数据文件(甚至日志文件)的问题时,我脑海中更大的问题是为什么?当你尝试时会发生什么坏事?看起来好像收缩操作已经完成。现在在这种情况下,它在某种意义上是有意义的——因为 MSDE/Express 版本的上限为最大 DB 大小。但正确的答案可能是查看适合您需求的正确版本。如果您偶然发现这个问题是为了缩小您的生产数据库,而这不是原因,您应该问自己为什么?问题。

我不希望有人在网上搜索“如何缩小数据库”并认为这是一件很酷或可以接受的事情。

收缩数据文件是一项特殊任务,应为特殊场合保留。考虑一下,当您缩小数据库时,您实际上是在对索引进行碎片化。考虑一下,当您收缩数据库时,您正在占用数据库可能有朝一日重新增长的可用空间 - 有效地浪费您的时间并导致收缩操作的性能损失只是为了看到数据库再次增长。

我在几篇关于缩小数据库的博客文章中写过这个概念。首先想到的是“不要触摸那个收缩按钮”。我讨论了这里概述的这些概念 - 以及“正确调整”数据库的概念。最好决定您的数据库需要多大,计划未来的增长并将其分配到该数量。借助 SQL Server 2005 及更高版本中可用于数据文件的即时文件初始化,增长的成本更低——但我仍然更喜欢有一个适当的初始应用程序——而且我对数据库中的空白空间的恐惧远比我害怕的要少得多普遍收缩,没有先考虑。:)

于 2013-11-16T13:34:15.157 回答
7

DBCC SHRINKDATABASE对我有用,但这是它的完整语法:

DBCC SHRINKDATABASE ( database_name, [target_percent], [truncate] )

其中target_percent是缩小数据库后数据库文件中剩余的所需可用空间百分比。

truncate参数可以是:

NOTRUNCATE

使释放的文件空间保留在数据库文件中。如果未指定,则释放的文件空间将释放给操作系统。

TRUNCATEONLY

将数据文件中所有未使用的空间释放给操作系统,并将文件收缩到最后分配的范围,在不移动任何数据的情况下减小文件大小。不会尝试将行重新定位到未分配的页面。使用 TRUNCATEONLY 时忽略 target_percent。

...是的 no_one 是对的,缩小数据库不是很好的做法,因为例如:

缩小数据文件是引入大量逻辑碎片的极好方法,因为它将页面从数据库文件的分配范围的末尾移动到文件前面的某个位置......

收缩数据库可能会对数据库、服务器产生很多影响……在你做之前要好好考虑一下!

网上有很多关于它的博客和文章。

于 2009-01-13T14:38:36.707 回答
5

迟到的答案,但可能对其他人有用

如果 DBCC ShrinkDatabase/ShrinkFile 或 SSMS (Tasks/Shrink/Database) 都没有帮助,Quest 和 ApexSQL 提供的工具可以完成工作,甚至在需要时安排定期收缩。

前段时间我在免费试用中使用过后者来执行此操作,在本文末尾进行了简短描述:

https://solutioncenter.apexsql.com/sql-server-database-shrink-how-and-when-to-schedule-and-perform-shrinking-of-database-files/

您需要做的就是安装 ApexSQL Backup,单击主功能区中的“收缩数据库”按钮,在弹出的窗口中选择数据库,然后单击“完成”。

于 2017-06-28T09:07:27.300 回答
4

你应该使用:

dbcc shrinkdatabase (MyDB)

它将缩小日志文件(保持 Windows 资源管理器打开并查看它的发生)。

于 2010-01-08T16:13:02.817 回答
4

您还需要缩小各个数据文件。

然而,缩小数据库并不是一个好主意。例如看这里

于 2009-01-13T14:26:55.967 回答
2

“因此有理由假设现在应该可以回收很多空间。”

抱歉,如果我误解了这个问题,但是您确定是数据库而不是日志文件占用了空间吗?检查数据库的恢复模式。很有可能它是完整的,这意味着日志文件永远不会被截断。如果您不需要每个事务的完整记录,您应该可以更改为 Simple,这将截断日志。您可以在此过程中收缩数据库。假设一切顺利,该过程如下所示:

  1. 备份数据库!
  2. 更改为简单恢复
  3. Shrink db(右键单击 db,选择所有任务 > 收缩 db -> 设置为 10% 可用空间)
  4. 验证空间是否已被回收,如果没有,您可能需要进行完整备份

如果这不起作用(或者当您尝试切换恢复模式时收到一条消息“日志文件已满”),请尝试以下操作:

  1. 备份
  2. 终止与数据库的所有连接
  3. 分离数据库(右键单击 > 分离或右键单击 > 所有任务 > 分离)
  4. 删除日志 (ldf) 文件
  5. 重新连接数据库
  6. 更改恢复模式

等等

于 2010-01-08T16:24:40.150 回答
2

这是另一个解决方案:使用数据库发布向导将您的架构、安全性和数据导出到 sql 脚本。然后,您可以使当前的数据库脱机并使用脚本重新创建它。

听起来有点愚蠢,但有几个优点。首先,没有丢失数据的机会。您的原始数据库(只要您在删除数据库时不删除它!)是安全的,新数据库将大致尽可能小,并且您将拥有当前数据库的两个不同快照 - 一个已准备好滚动,一个缩小 - 您可以选择备份。

于 2009-01-13T14:48:29.917 回答
1

尽管我需要在 MSSQL 2012 版本上进行 SHRINKFILE,但我还是遇到了这篇文章,这自 2000 或 2005 版本以来就有点棘手了。在阅读了与此问题相关的所有风险和问题后,我最终进行了测试。长话短说,我得到的最好结果来自使用MS SQL Server Management Studio

Right-Click the DB -> TASKS -> SHRINK -> FILES -> select the LOG file
于 2014-07-23T18:11:16.183 回答
0

删除数据,确保恢复模型简单,然后 skrink(收缩数据库或收缩文件都可以)。如果数据文件仍然太大,并且您使用堆来存储数据 - 也就是说,大型表上没有聚集索引 - 那么您可能会遇到有关从堆中删除数据的问题:http: //support.microsoft.com /kb/913399

于 2009-08-19T18:04:20.520 回答
0

您还必须修改数据和日志文件的最小大小。DBCC SHRINKDATABASE 将收缩您已经分配的文件中的数据。要将文件缩小到小于其最小大小,请使用 DBCC SHRINKFILE 并指定新大小。

于 2009-01-13T14:16:12.743 回答
0

我最近做了这个。我试图制作一个紧凑版本的数据库以便在路上进行测试,但无论我删除了多少行,我都无法缩小它。最终,在这个线程中的许多其他命令之后,我发现我的聚集索引在删除行后没有得到重建。重建我的索引使我可以正确收缩。

于 2011-07-11T19:00:45.617 回答
0

我认为您可以通过从完全恢复切换到简单恢复来删除所有日志。右键单击您的数据库并选择Properties并选择Options并更改

  • Recovery modeSimple
  • Containment typeNone

从完整切换到简单

于 2017-12-31T23:22:14.287 回答
0

不确定这有多实用,取决于数据库的大小、表的数量和其他复杂性,但我:

  1. 对物理驱动器进行碎片整理
  2. 根据我的要求,空间,百分比增长等创建一个新的数据库
  3. 使用简单的 ssms 任务将旧数据库中的所有表导入新数据库
  4. 编写旧数据库上所有表的索引,然后在新数据库上重新创建索引。根据需要扩展外键等。
  5. 根据需要重命名数据库,确认成功,删除旧的
于 2015-09-01T14:45:54.347 回答
0

当您将恢复模式设置为简单(并启用自动收缩)时,SQL Server 仍有可能无法收缩日志。它与日志中的检查点(或缺少检查点)有关。

所以首先运行

DBCC CHECKDB

在您的数据库上。之后,收缩操作应该像魅力一样工作。

通常我使用Tasks>Shrink>Files菜单并选择带有重新组织页面选项的日志文件。

于 2020-06-04T11:50:56.817 回答