【问题标题】:SQL Server move "table free space" to "database free space"SQL Server 将“表可用空间”移动到“数据库可用空间”
【发布时间】:2017-09-27 10:28:48
【问题描述】:

我有一个相当大的数据库(最多有几百个分片的每日表,mdf 文件总共有 1.3TB)。

现在我们想尽最大努力阻止 mdf 进一步增长,我们会从现有表中删除尽可能多的不必要数据。

我们所知道的:

  1. 从表中删除数据不会减小 mdf 文件大小。
  2. 收缩文件/数据库是不可能的。
  3. 除非重建旧表,否则从旧表(例如 table_20161231)中删除不会为新表(例如 table_20170927)释放数据库空间。

所以我们知道表重建是必要的,改变索引似乎没有帮助,根据“exec sp_spaceused”的结果,空间仍然没有释放。

因此我们现在在下面做:

  1. 从 table_20161231 中删除,其中 data = 'unnecessary';
  2. select * into table_20161231_compact from table_20161231
  3. 删除表table_20161231

再次执行“exec sp_spaceused”似乎显示出积极的结果,因为新表有更多的“未分配空间”。

有人知道释放已删除数据空间的 1 行方法吗?

【问题讨论】:

  • >>>从旧表中删除(比如 table_20161231)不会为新表释放数据库空间
  • @sepupic,您问的问题似乎超出了我的知识范围,我只是从非常简单的表中进行非常简单的删除,我如何找出您需要知道的内容?
  • 很简单。在 SSMS 中为您的表编写脚本,看看它是否有 CLUSTERED 索引。如果一个表没有 CLUSTERED 索引,那么它就是一个堆。请检查它,这很重要,因为如果不是在某些条件下,堆不会释放可用空间
  • @sepupic 我尝试编写 create table 语句的脚本,但上面没有聚集索引..
  • 所以和我想的一样,是一堆。我将在稍后发布带有链接的答案并解释如何避免这种情况

标签: sql-server


【解决方案1】:

当您从表中删除时,SQL Server 会保留该空间以供重复使用,因为它假定它最终会被填满。如果你想要它回来,不幸的推卸是唯一的方法。它可能充满危险,但作为一个你知道数据不会增长到那个大小并且你处理索引碎片之后它应该没问题的地方......

您所做的方式可能是最安全的方式,您可以编写脚本并使用sp_rename 更改表名。

Mike Walsh 写了一篇不错的博客,讲述了当你收缩时会发生什么HERE

【讨论】:

  • hmm 我们希望避免收缩,因为这是一个实时生产数据库,每秒有许多事务在进行,我们希望尽量减少做一些占用大量资源的事情的需要,因为示例高清 IO..
  • @dbajtr OP的问题不在于向OS释放空间,他从堆中删除并且它们没有向数据库释放空间,空闲页面仍然分配给堆删除后。
【解决方案2】:

所以你从堆中删除。如果您只是删除行,堆不会释放空间,可能的解决方法是创建聚集索引或使用tablock 删除:

Deleting Rows by Using DELETE

从堆中删除行 当从堆中删除行时,数据库引擎可能会为操作使用行或页锁定。作为一个 结果,被删除操作清空的页面仍然被分配 到堆。当空页未被释放时,关联的 空间不能被数据库中的其他对象重用。删除 堆中的行和释放页,请使用以下方法之一。

  • 在 DELETE 语句中指定 TABLOCK 提示。使用 TABLOCK 提示会导致删除操作在表上获取共享锁
    而不是行锁或页锁。这允许页面是
    解除分配。有关 TABLOCK 提示的详细信息,请参阅表
    提示 (Transact-SQL)。
  • 如果要从表中删除所有行,请使用 TRUNCATE TABLE。
  • 在删除行之前在堆上创建聚集索引。您可以在删除行后删除聚集索引。这个方法
    比以前的方法更耗时,使用更多
    临时资源。

以防万一您不知道如何使用tablock,这是一个示例:

delete dbo.myTbl with(tablock)
where...

附言

因此我们现在在下面做:

delete from  where data = 'unnecessary';
select * into table_20161231_compact from table_20161231
drop table table_201table_2016123161231

有人知道释放已删除数据空间的 1 行方法吗?

是的,从 SQL Server 2008 开始,可以在 1 个命令中完成:

alter table table_20161231 rebuild

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    • 2010-10-26
    • 2019-02-17
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多