【问题标题】:How do I shrink my SQL Server Database?如何缩小我的 SQL Server 数据库?
【发布时间】:2010-10-01 03:27:50
【问题描述】:

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

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

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

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

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

还是 1.9Gb

为什么?

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

【问题讨论】:

    标签: sql-server database shrink msde2000


    【解决方案1】:
    ALTER DATABASE MyDatabase SET RECOVERY SIMPLE
    
    GO
    
    DBCC SHRINKFILE (MyDatabase_Log, 5)
    
    GO
    
    ALTER DATABASE MyDatabase SET RECOVERY FULL
    
    GO
    

    【讨论】:

    • 注意:这意味着您不需要 LDF 文件中的内容。将恢复模式设置为简单并缩小日志文件会永久删除其中的所有日志。
    • 如何在 Windows 调度程序中将其用作计划任务?我也想从 sqlcmd 提示符中使用它?我尝试将此 dbbccshrink 命令放在 .sql 文件扩展名中:REM 运行 SQL 文件以缩小 mydb11 日志文件 SQLCMD -S .\SQLEXPRESS -i "mydb11" 但 .\sqlexpress 的含义是什么?
    【解决方案2】:

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

    【讨论】:

    • 如果有人需要以编程方式执行此操作,这可能会很有用
    【解决方案3】:

    这是一个老问题,但我只是碰巧。

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

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

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

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

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

    【讨论】:

    • 我找到了这个参考资料(法语不好),它可以帮助人们理解为什么在没有正确或专门的情况下收缩数据文件是不好的。 mcherif.wordpress.com/2012/12/01/…
    • @Mike Walsh - 谢谢。我不知道潜在的性能影响。如果收缩确实不可避免(由于错误的数据计划),有没有办法可以对索引进行碎片整理 - 在收缩完成后。我的理解是MSSQL没有这样的功能,还是想确认一下。
    【解决方案4】:

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

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

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

    truncate参数可以是:

    NOTRUNCATE
    

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

    TRUNCATEONLY
    

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

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

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

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

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

    【讨论】:

    • 这不会是正常的事情......我这样做是因为其他相关的数据库接近 2Gb,这是 MSDE2000 的限制。理论上,我将删除 50% 的“项目”记录以及许多其他表中与它们相关的所有项目......项目大约占系统的 50%。
    【解决方案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,点击主功能区中的“收缩数据库”按钮,在弹出的窗口中选择数据库,然后点击“完成”。

    【讨论】:

      【解决方案6】:

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

      但是,缩小数据库并不是一个好主意。例如见here

      【讨论】:

      • 链接示例需要注册(电子邮件地址)才能阅读。也许this 是一个更好的例子?
      【解决方案7】:

      你应该使用:

      dbcc shrinkdatabase (MyDB)
      

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

      【讨论】:

      • 自然不会触及你的数据,只会触及日志文件。
      【解决方案8】:

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

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

      【讨论】:

      • 非常有趣。我将在本地尝试这个,以了解真正的最小尺寸应该是多少。但是我需要能够在几个客户端的机器上运行这个过程。最好通过运行单个脚本而不是数据库的导出/导入。
      • 您知道数据库大小与脚本大小的典型比例吗?
      • 我为示例 1.3Gb 数据库生成了一个脚本,它的大小为 9.8 Gb。我什至不知道如何运行这么大的脚本。
      • 这太疯狂了。我认为你在这个大世界中是另一个世界。
      【解决方案9】:

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

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

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

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

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

      等等

      【讨论】:

        【解决方案10】:

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

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

        【讨论】:

        • 再一次,他试图减少数据文件而不是日志文件。
        【解决方案11】:

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

        【讨论】:

        • 嗯,最小尺寸确实被报告为与当前尺寸相同。但是我找不到减少这个值的方法 DBCC Shrinkfile 似乎没有效果。
        【解决方案12】:

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

        【讨论】:

          【解决方案13】:

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

          【讨论】:

            【解决方案14】:

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

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

            【讨论】:

              【解决方案15】:

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

              • Recovery modeSimple
              • Containment typeNone

              【讨论】:

                【解决方案16】:

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

                所以先运行

                DBCC CHECKDB
                

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-06-20
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多