如何缩小 SQL Server 数据库?
我有一个数据库大小接近 1.9Gb,而 MSDE2000 不允许数据库超过 2.0Gb,
我需要缩小此数据库(以及在不同客户端位置的许多其他类似数据库)。
我发现并删除了数百条或数千条被认为不需要的记录: 这些记录占数据库中一些主要(最大)表的很大一部分。 因此,可以合理地假设现在应该有很多空间是可检索的。
所以现在我需要缩小数据库以解决丢失的记录。
- 我执行
DBCC ShrinkDatabase('MyDB')
……没有效果。 - 我已经尝试了MSSMS中提供的各种收缩工具......仍然没有效果。
- 我已经备份了数据库并恢复了...仍然没有效果。
还是 1.9Gb
为什么?
无论我最终发现什么过程都需要在客户端机器上重播,除了 OSql 或类似的东西之外,什么都不能访问。
I have a Database nearly 1.9Gb Database in size, and MSDE2000 does not allow DBs that exceed 2.0Gb
I need to shrink this DB (and many others like this at various client locations).
I have found and deleted many 100's of 1000's of records which are considered unneeded:
these records account for a large percentage of some of the main (largest) tables in the Database. Therefore it's reasonable to assume much space should now be retrievable.
So now I need to shrink the DB to account for the missing records.
- I execute
DBCC ShrinkDatabase('MyDB')
...... No effect. - I have tried the various shrink facilities provided in MSSMS.... Still no effect.
- I have backed up the database and restored it... Still no effect.
Still 1.9Gb
Why?
Whatever procedure I eventually find needs to be replayable on a client machine with access to nothing other than OSql or similar.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
这可能看起来很奇怪,但它对我有用,我已经编写了一个 C# 程序来自动执行此操作。
步骤 1:截断事务日志(仅备份事务日志,打开删除非活动事务的选项)
步骤 2:运行数据库收缩,将所有页面移动到文件的开头
步骤 3:再次截断事务日志,因为步骤 2 添加了日志条目
步骤 4:再次运行数据库收缩。
我使用 SQL DMO 库的精简代码如下:
This may seem bizarre, but it's worked for me and I have written a C# program to automate this.
Step 1: Truncate the transaction log (Back up only the transaction log, turning on the option to remove inactive transactions)
Step 2: Run a database shrink, moving all the pages to the start of the files
Step 3: Truncate the transaction log again, as step 2 adds log entries
Step 4: Run a database shrink again.
My stripped down code, which uses the SQL DMO library, is as follows:
DBCC SHRINKDATABASE
对我有用,但这是它的完整语法:其中
target_percent
是数据库收缩后数据库文件中剩余可用空间的所需百分比。truncate
参数可以是:使释放的文件空间保留在数据库文件中。 如果未指定,则释放的文件空间将释放给操作系统。
导致数据文件中任何未使用的空间释放给操作系统,并将文件缩小到最后分配的范围,从而在不移动任何数据的情况下减小文件大小。 不会尝试将行重新定位到未分配的页。 当使用 TRUNCATEONLY 时,target_percent 被忽略。
...是的,no_one 是对的,收缩数据库并不是很好的做法,因为例如:
收缩数据文件是引入显着逻辑碎片的绝佳方法,因为它将页面从数据库文件分配范围的末尾移动到某个地方在文件的前面...
收缩数据库可能会对数据库、服务器产生很多影响...在执行此操作之前请仔细考虑!
网络上有很多关于它的博客和文章。
DBCC SHRINKDATABASE
works for me, but this is its full syntax:where
target_percent
is the desired percentage of free space left in the database file after the database has been shrunk.And
truncate
parameter can be:Causes the freed file space to be retained in the database files. If not specified, the freed file space is released to the operating system.
Causes any unused space in the data files to be released to the operating system and shrinks the file to the last allocated extent, reducing the file size without moving any data. No attempt is made to relocate rows to unallocated pages. target_percent is ignored when TRUNCATEONLY is used.
...and yes no_one is right, shrinking datbase is not very good practice becasue for example :
shrink on data files are excellent ways to introduce significant logical fragmentation, becasue it moves pages from the end of the allocated range of a database file to somewhere at the front of the file...
shrink database can have a lot of consequence on database, server.... think a lot about it before you do it!
on the web there are a lot of blogs and articles about it.
这是一个老问题了,但我只是碰巧想到了它。
真正简短而正确的答案已经给出,并且获得了最多的选票。 这就是如何缩小事务日志,这可能是OP的问题。 当事务日志增长失控时,通常需要将其收缩,但应注意防止日志未来出现失控的情况。 这个问题关于 dba.se 解释了这一点。 基本上 - 通过适当的恢复模型、事务日志维护、事务管理等,首先不要让它变得那么大。
但是,当阅读这个关于收缩数据的问题时,我脑海中更大的问题是文件(甚至日志文件)的内容是为什么?和尝试时会发生什么不好的事情?看起来好像收缩操作已经完成。 现在,在这种情况下,它在某种意义上是有意义的 - 因为 MSDE/Express 版本有最大数据库大小的上限。 但正确的答案可能是查看适合您需求的版本。 如果您偶然发现这个问题,希望缩小您的生产数据库,那么这不是您应该问自己为什么?问题的原因。
我不希望有人在网上搜索“如何缩小数据库”时发现这一点,并认为这是一件很酷或可以接受的事情。
收缩数据文件是一项特殊任务,应为特殊场合保留。 考虑一下,当您收缩数据库时,您实际上正在对索引进行碎片化。 考虑一下,当您收缩数据库时,您正在拿走数据库有一天可能会重新增长的可用空间 - 这实际上浪费了您的时间,并导致收缩操作的性能下降,结果却看到数据库再次增长。
我在几篇有关缩小数据库的博客文章中讨论了这个概念。 这个名为“不要触摸那个收缩按钮”首先浮现在脑海中。 我谈论这里概述的这些概念 - 还有“调整数据库大小”的概念。 更好的做法是决定您的数据库大小需要多少,规划未来的增长,并将其分配到该数量。 由于 SQL Server 2005 及更高版本中可用于数据文件的即时文件初始化,增长的成本较低 - 但我仍然更喜欢有一个适当的初始应用程序 - 而且我对数据库中的空白远不如对数据库中的空白感到害怕总体上没有想到先收缩。 :)
This is an old question, but I just happened upon it.
The really short and correct answer is already given and has the most votes. That is how you shrink a transaction log, and that was probably the OP's problem. And when the transaction log has grown out of control, it often needs to be shrunk back, but care should be taken to prevent future situations of a log from growing out of control. This question on dba.se explains that. Basically - Don't let it get that large in the first place through proper recovery model, transaction log maintenance, transaction management, etc.
But the bigger question in my mind when reading this question about shrinking the data file (or even the log file) is why? and what bad things happen when you try? It appears as though shrink operations were done. Now in this case it makes sense in a sense - because MSDE/Express editions are capped at max DB size. But the right answer may be to look at the right version for your needs. And if you stumble upon this question looking to shrink your production database and this isn't the reason why you should ask yourself the why? question.
I don't want someone searching the web for "how to shrink a database" coming across this and thinking it is a cool or acceptable thing to do.
Shrinking Data Files is a special task that should be reserved for special occasions. Consider that when you shrink a database, you are effectively fragmenting your indexes. Consider that when you shrink a database you are taking away the free space that a database may someday grow right back into - effectively wasting your time and incurring the performance hit of a shrink operation only to see the DB grow again.
I wrote about this concept in several blog posts about shrinking databases. This one called "Don't touch that shrink button" comes to mind first. I talk about these concepts outlined here - but also the concept of "Right-Sizing" your database. It is far better to decide what your database size needs to be, plan for future growth, and allocate it to that amount. With Instant File Initialization available in SQL Server 2005 and beyond for data files, the cost of growth is lower - but I still prefer to have a proper initial application - and I'm far less scared of white space in a database than I am of shrinking in general with no thought first. :)
您应该使用:
它将缩小日志文件(保持 Windows 资源管理器打开并查看它发生的情况)。
You should use:
It will shrink the log file (keep a windows explorer open and see it happening).
迟到的答案,但可能对其他人有用
如果 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,单击主功能区中的“收缩数据库”按钮,选择数据库弹出窗口,然后单击“完成”。
Late answer but might be useful useful for someone else
If neither DBCC ShrinkDatabase/ShrinkFile or SSMS (Tasks/Shrink/Database) doesn’t help, there are tools from Quest and ApexSQL that can get the job done, and even schedule periodic shrinking if you need it.
I’ve used the latter one in free trial to do this some time ago, by following short description at the end of this article:
https://solutioncenter.apexsql.com/sql-server-database-shrink-how-and-when-to-schedule-and-perform-shrinking-of-database-files/
All you need to do is install ApexSQL Backup, click "Shrink database" button in the main ribbon, select database in the window that will pop-up, and click "Finish".
您还需要缩小各个数据文件。
然而,缩小数据库并不是一个好主意。 例如,请参阅此处
You will also need to shrink the individual data files.
It is however not a good idea to shrink the databases. For example see here
这是另一个解决方案:使用数据库发布向导< /a> 将架构、安全性和数据导出到 sql 脚本。 然后,您可以使当前数据库脱机并使用脚本重新创建它。
听起来有点愚蠢,但有几个优点。 首先,不会丢失数据。 您的原始数据库(只要您在删除数据库时不删除它!)是安全的,新数据库将大致尽可能小,并且您将拥有当前数据库的两个不同快照 - 一个已准备好滚动,缩小 - 您可以选择备份。
Here's another solution: Use the Database Publishing Wizard to export your schema, security and data to sql scripts. You can then take your current DB offline and re-create it with the scripts.
Sounds kind of foolish, but there are a couple advantages. First, there's no chance of losing data. Your original db (as long as you don't delete your DB when dropping it!) is safe, the new DB will be roughly as small as it can be, and you'll have two different snapshots of your current database - one ready to roll, one minified - you can choose from to back up.
“因此,可以合理地假设现在应该有很多空间是可回收的。”
如果我误解了这个问题,我很抱歉,但是您确定是数据库而不是日志文件占用了空间吗? 检查数据库采用的恢复模式。很可能是完整恢复模式,这意味着日志文件永远不会被截断。 如果您不需要每笔交易的完整记录,您应该可以更改为 Simple,这会截断日志。 您可以在此过程中收缩数据库。 假设一切顺利,该过程如下所示:
如果没有不起作用(或者当您尝试切换恢复模式时收到一条消息说“日志文件已满”),请尝试以下操作:
等。
"Therefore it's reasonable to assume much space should now be retrievable."
Apologies if I misunderstood the question, but are you sure it's the database and not the log files that are using up the space? Check to see what recovery model the database is in. Chances are it's in Full, which means the log file is never truncated. If you don't need a complete record of every transaction, you should be able to change to Simple, which will truncate the logs. You can shrink the database during the process. Assuming things go right, the process looks like:
If that doesn't work (or you get a message saying "log file is full" when you try to switch recovery modes), try this:
etc.
尽管我需要在 MSSQL 2012 版本上 SHRINKFILE,但我还是看到了这篇文章,这自 2000 或 2005 版本以来有点棘手。 在阅读了与此问题相关的所有风险和问题后,我结束了测试。 长话短说,我获得的最佳结果是使用 MS SQL Server Management Studio。
I came across this post even though I needed to SHRINKFILE on MSSQL 2012 version which is little trickier since 2000 or 2005 versions. After reading up on all risks and issues related to this issue I ended up testing. Long story short, the best results I got were from using the MS SQL Server Management Studio.
您还必须修改数据和日志文件的最小大小。 DBCC SHRINKDATABASE 将收缩您已分配的文件内的数据。 要将文件缩小到小于其最小大小,请使用 DBCC SHRINKFILE 并指定新大小。
You also have to modify the minimum size of the data and log files. DBCC SHRINKDATABASE will shrink the data inside the files you already have allocated. To shrink a file to a size smaller than its minimum size, use DBCC SHRINKFILE and specify the new size.
删除数据,确保恢复模型简单,然后进行skrink(收缩数据库或收缩文件都可以)。 如果数据文件仍然太大,并且您使用堆来存储数据(即大表上没有聚集索引),那么您可能会遇到从堆中删除数据的问题:http://support.microsoft.com/kb/913399
Delete data, make sure recovery model is simple, then skrink (either shrink database or shrink files works). If the data file is still too big, AND you use heaps to store data -- that is, no clustered index on large tables -- then you might have this problem regarding deleting data from heaps: http://support.microsoft.com/kb/913399
我最近做了这个。 我试图制作一个紧凑版本的数据库以便在路上进行测试,但无论我删除了多少行,我都无法缩小它。 最终,在该线程中的许多其他命令之后,我发现我的聚集索引在删除行后没有重建。 重建我的索引使我可以正确收缩。
I recently did this. I was trying to make a compact version of my database for testing on the road, but I just couldn't get it to shrink, no matter how many rows I deleted. Eventually, after many other commands in this thread, I found that my clustered indexes were not getting rebuilt after deleting rows. Rebuilding my indexes made it so I could shrink properly.
不确定这有多实用,并且取决于数据库的大小、表的数量和其他复杂性,但我:对
Not sure how practical this would be, and depending on the size of the database, number of tables and other complexities, but I:
我认为您可以通过从完整恢复切换到简单恢复来删除所有日志。 右键单击您的数据库并选择
属性
,然后选择选项
并将恢复模式
更改为简单
包含类型
到无
I think you can remove all your log with switch from full to simple recovery. Right click on your Database and select
Properties
and selectOptions
and changeRecovery mode
toSimple
Containment type
toNone
当您将恢复模式设置为“简单”(并启用自动收缩)时,SQL Server 仍然可能无法收缩日志。 它与日志中的检查点(或缺乏)有关。
因此,首先
在您的数据库上运行。 之后,收缩操作应该会发挥作用。
通常我使用任务>收缩>文件菜单并选择带有重新组织页面选项的日志文件。
When you've set the recovery model to Simple (and enabled auto-shrink), it is still possible that SQL Server can not shrink the log. It has to do with checkpoints in the log (or lack thereof).
So first run
on your database. After that the shrink operation should work like a charm.
Usually I use the Tasks>Shrink>Files menu and choose the logfile with the option to reorganise pages.