我知道这是在各种论坛上讨论最多的答案:我完全理解在大多数情况下答案是否定的。
但是想知道在任何情况下它是否都是好方法:
假设当前的产品数据库在我们的例子中超过 30 TB,并且数据保留了 1 年。表大多是压缩和分区的。
开发团队提出了他们不需要数据来保持长达一年的逻辑,并希望将保留期更改为 6 个月。因此,预计清除后数据将减少一半,并且只有 6 个月的数据。
这是我们被要求缩小数据文件的地方,以便可以返回那些具有 TB 空间的 LUN,或者如果我们迁移到新的 sql 版本,我们会要求让我们说少一些(大约 10)TB,这样可以节省一些钱,假设我们为未来的数据库增长保留了 5Tb 的额外空间。
在这种情况下,如果我们假设在低峰值时间阻塞可以被接受或者如果收缩运行更长的时间可以被取消,那么我们在小块中进行收缩会有所帮助吗?
上述收缩数据文件活动的价值是多少,还是有更好的方法?
编辑 --> 我们正在迁移到最新版本,可能是 SQL 2017 或 SQL2K19。这些表不是基于文件组进行分区的,因为对于这个数据库,所有 30 多个文件都在主数据库上。我知道,它只是一个供应商数据库设计,我手里没有太多东西。
您可以在此处阅读相关信息 - https://www.brentozar.com/archive/2017/12/whats-bad-shrinking-databases-dbcc-shrinkdatabase/
关于什么时候必须缩小,你可以在这里做什么 - https://www.brentozar.com/archive/2020/07/what-if-you-really-do-need-to-shrink-a-database/
当我们缩小数据库时,它会引入外部和内部碎片,它会导致阻塞,它会在运行时导致事务日志增长。索引碎片变高。当我们重建索引时,数据库大小会恢复。因此造成了无限循环的收缩重建。
假设您有适当的停机时间,并且如果我必须缩小以移动数据库,我将编写所有索引并删除它们。多次运行检查点,进行日志备份,收缩日志文件然后收缩数据库,进行完整备份并将此备份恢复到新位置。运行索引脚本以再次创建它们并让它在新服务器中增长。注意:在 30TB 上创建索引会很痛苦。
可能有更好的方法来做到这一点,我很乐意关注其他答案。
这是一个非常庞大的数据库,需要缩小。在开始收缩操作之前,我只想指出您要检查的两件事:
LOB 数据。这将永远持续下去,因为 LOB 数据没有反向指针。即,一个LOB 页面被移动并且所有SQL Server 都知道它属于哪个表。它必须进行表扫描才能找到该行,该行对应于该页面上的每个 lob 值。
堆表。对于移动的每个页面,SQL Server 必须修改该页面上每一行的每个 nc 索引。与聚簇表相比,缩小堆表所需的时间很容易延长 5-10 倍。
对于该大小,您可能要考虑的一个选项是在收缩之前将数据移动到其他位置(文件组)(或者如果该文件组现在为空,则可能只是删除该文件组)。
一种可能性是使用事务复制并添加静态行过滤器来过滤掉旧数据,这也将具有缩短新服务器时间的优势(我假设您正在进行并行迁移不是就地升级)。