如何缩小SQL Server数据库?

时间:2009-01-13 14:13:05

标签: sql-server database shrink msde2000

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

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

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

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

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

仍然是1.9Gb

为什么?

我最终发现的任何程序都需要在客户端计算机上重放,只能访问OSql或类似的东西。

16 个答案:

答案 0 :(得分:90)

ALTER DATABASE MyDatabase SET RECOVERY SIMPLE

GO

DBCC SHRINKFILE (MyDatabase_Log, 5)

GO

ALTER DATABASE MyDatabase SET RECOVERY FULL

GO

答案 1 :(得分:10)

这可能看起来很奇怪,但它对我有用,我编写了一个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);

答案 2 :(得分:7)

这是一个老问题,但我刚发生了。

已经给出了真正简短且正确的答案并获得最多票数。这是如何缩小事务日志,这可能是OP问题。当事务日志失去控制时,通常需要缩减,但应注意防止日志日益失控。 dba.se上的这个问题解释了这一点。 基本上 - 通过适当的恢复模式,事务日志维护,事务管理等,不要让它变得那么大。

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

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

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

我在几篇关于缩小数据库的博客文章中写过这个概念。首先想到这个名为“Don't touch that shrink button”的名字。我谈到了这里概述的这些概念 - 还有“正确调整”数据库的概念。最好确定您的数据库大小需要什么,计划未来增长并将其分配给该数量。使用SQL Server 2005及更高版本的数据文件中的即时文件初始化,增长成本较低 - 但我仍然希望有一个正确的初始应用程序 - 而且我对数据库中的空白区域的害怕远不如我一般没有先考虑就缩小了。 :)

答案 3 :(得分:5)

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

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

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

truncate参数可以是:

NOTRUNCATE

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

TRUNCATEONLY

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

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

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

收缩数据库会对数据库,服务器产生很大的影响......在你做之前要考虑很多!

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

答案 4 :(得分:5)

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

如果DBCC ShrinkDatabase / ShrinkFile或SSMS(任务/收缩/数据库)都没有帮助,Quest和ApexSQL的工具可以完成工作,甚至可以根据需要安排定期收缩。

我已经在免费试用版中使用了后者,通过遵循本文末尾的简短描述来做到这一点:

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

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

答案 5 :(得分:4)

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

缩小数据库并不是一个好主意。例如,请参阅here

答案 6 :(得分:4)

您应该使用:

dbcc shrinkdatabase (MyDB)

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

答案 7 :(得分:2)

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

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

答案 8 :(得分:2)

“因此,假设现在应该可以检索到很多空间是合理的。”

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

  1. 备份数据库!
  2. 更改为简单恢复
  3. 缩小数据库(右击数据库,选择所有任务>缩小数据库 - >设置为10%可用空间)
  4. 确认已回收空间,否则您可能需要进行完整备份
  5. 如果这不起作用(或者当您尝试切换恢复模式时收到“日志文件已满”的消息),请尝试以下操作:

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

答案 9 :(得分:1)

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

Right-Click the DB -> TASKS -> SHRINK -> FILES -> select the LOG file

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

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

  • Recovery modeSimple
  • Containment typeNone

Switching from full to simple

答案 15 :(得分:0)

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

所以先运行

DBCC CHECKDB

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

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