截断了200GB的表,但未释放磁盘空间


Answers:


25

如果要引用卷上的实际数据库文件消耗,则SQL Server不会自动处理它。仅仅因为您从数据库中删除了数据并不意味着数据库文件将缩小以仅适合现有数据。

如果您需要回收卷上的空间,则需要使用来缩小特定文件DBCC SHRINKFILE。根据该文档,值得注意一些最佳实践:

最佳实践

计划收缩文件时,请考虑以下信息:

  • 在创建大量未使用空间的操作(例如截断表或删除表操作)之后,收缩操作最有效。

  • 大多数数据库都需要一些可用空间才能用于常规的日常操作。如果您反复收缩数据库,并发现数据库大小再次增加,则表明常规操作需要收缩的空间。在这些情况下,重复收缩数据库是浪费的操作。

  • 收缩操作不会保留数据库中索引的碎片状态,通常会将碎片增加到一定程度。这是不反复收缩数据库的另一个原因。

  • 顺序而不是同时收缩同一数据库中的多个文件。系统表上的争用可能由于阻塞而导致延迟。

还要注意:

DBCC SHRINKFILE 可以在过程中的任何时候停止操作,并保留所有已完成的工作。

执行此操作时肯定要考虑一些事情,我建议您看一下Paul Randal的博客文章,了解执行此操作时会发生什么。

第一步肯定是要验证您实际上可以替换多少空间和可用空间,以及文件上的已用空间:

use AdventureWorks2012;
go

;with db_file_cte as
(
    select
        name,
        type_desc,
        physical_name,
        size_mb = 
            convert(decimal(11, 2), size * 8.0 / 1024),
        space_used_mb = 
            convert(decimal(11, 2), fileproperty(name, 'spaceused') * 8.0 / 1024)
    from sys.database_files
)
select
    name,
    type_desc,
    physical_name,
    size_mb,
    space_used_mb,
    space_used_percent = 
        case size_mb
            when 0 then 0
            else convert(decimal(5, 2), space_used_mb / size_mb * 100)
        end
from db_file_cte;

6

当您截断表时,这是正常现象,并且涉及到根据Per Books Online删除128个以上的盘区

当您删除或重建大型索引,或删除或截断大型表时,数据库引擎会推迟实际的页面解除分配及其关联的锁,直到事务提交之后。此实现在多用户环境中支持自动提交和显式事务,并且适用于使用超过128个扩展数据块的大型表和索引。

数据库引擎通过将进程分为两个单独的阶段(逻辑阶段和物理阶段),避免了删除大对象所需的分配锁。

在逻辑阶段,表或索引使用的现有分配单元被标记为要释放并锁定,直到事务提交。使用删除的聚集索引,将复制数据行,然后将其移动到为存储创建的新分配单元,即重建的聚集索引或堆。(在重建索引的情况下,数据行也会排序。)发生回滚时,仅需要回滚此逻辑阶段。

物理阶段发生在事务提交之后。标记为要重新分配的分配单位实际上是分批丢弃的。这些丢弃是在后台发生的短事务中处理的,不需要很多锁。

因为物理阶段是在事务提交之后发生的,所以表或索引的存储空间可能仍显示为不可用。如果在物理阶段完成之前数据库需要此空间才能增长,则数据库引擎会尝试从标记为要释放的分配单元中恢复空间。要查找这些分配单元当前使用的空间,请使用sys.allocation_units目录视图。

延迟的放置操作不会立即释放分配的空间,它们会在数据库引擎中带来额外的开销成本。因此,就像在SQL Server 2000中一样,删除,截断和重建使用128个或更少扩展区的表和索引。这意味着逻辑阶段和物理阶段都在事务提交之前发生。

您将不得不等待,当然,您将不得不手动收缩文件以回收空间,还值得一提的是,收缩会导致逻辑碎片,除非有严重需求,否则应避免收缩。您将不得不在缩小和碎片化之间取得平衡。考虑到数据无论如何都会再次增长的情况,最好问问自己收缩是否会真正解决问题。

使用下面的查询来检查数据库中有多少可用空间

SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB
FROM sys.database_files;

6

除了Tom和Shanky的答案外,如果您的数据库包含LOB / BLOB数据,则DBCC SHRINKFILE可能不起作用。如果是这种情况,那么您有两种选择,具体取决于是否可以使数据库脱机。如果您可以使数据库脱机,则需要将数据复制出来,然后再复制回去以删除空白空间。您可以通过以下任一方法完成此操作:

  1. 使用SELECT INTO语句将整个表转移到新表。删除原始表,运行DBCC SHRINKFILE。将新表重命名为原始表名。
  2. 使用bcp以模式复制表,删除表,运行DBCC SHRINKFILE,创建表,然后将数据bcp到表中。
  3. 使用导出/导入将所有数据移动到新数据库,删除现有数据库,将新数据库重命名为原始数据库名称。

如果无法使数据库脱机,则可以将DBCC SHRINKFILE命令与EMPTYFILE选项一起使用。

脱机副本的详细信息:http : //support.microsoft.com/kb/324432/en-us

EMPTYFILE选项的当前信息 http://msdn.microsoft.com/zh-cn/library/ms189493(v=sql.105).aspx

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.