我有一个包含 2.6B 行的表,我需要将一列从 Char(1) 更改为 Varchar(64)。该表超过 300GB,有几个索引。该列可以为空,所以我正在运行的事务是:
ALTER TABLE XXXX ALTER COLUMN YYYYY varchar(64) NULL
我知道这是一个记录操作,所以我将事务日志的大小预先设置为 300GB,认为这已经足够了,尤其是每 5 分钟备份一次日志以允许日志空间重用。由于驱动器空间问题,在我不得不取消交易之前,交易日志增长到 812GB。
我还经历了数据文件 USED 大小的大幅增加,我不知道为什么会这样。使用的数据文件大小正好在 200GB 左右(在这个数据库中完成的事务非常少,所以我知道增加来自这个 alter table 命令)。
我有一些问题:
- 为什么只是从 char(1) 更改为 varchar(64) 时数据文件会增加?我的印象是,这不应该改变存储的数据量,除非自 varchar 以来实际需要该空间。由于 char(1) 是现有数据类型,所有现有值要么为空,要么为 1 字节,无需扩展现有数据。
- 在试图弄清楚如何更好地做到这一点时,我从 Aaron Bertrand 那里得到了这个答案,它似乎也适用于我的情况。这会是完成这项任务的更好方法吗?
- 该数据库位于 2 节点同步提交 AG 中,我注意到 redo_queue_size 超过 130GB,这意味着主数据库发送日志数据的速度比辅助数据库应用它们的速度更快。这意味着当日志备份完成时,主节点上的日志无法截断。这是这样的正常行为吗?alter column 语句是否作为一个大事务处理?如果是这样,那将解释为什么日志不断增长。
我认为 VARCHAR 的最小存储空间为 4 个字节,因此您确实将列的大小从 1 个字节更改为至少 4 个字节,导致(如您所见)随着列的增长和其他周围的东西。
我会推荐 Aaron 的方法作为实现相同目的的更快方法。它的缺点是不保留列顺序....但是由于我们应该始终(大声笑)使用命名列进行选择和插入,因此存储顺序无关紧要。(可能需要刷新框架......)
你是对的。DDL 是一个记录的事务,因此您在日志文件/AG 运行状况中观察到的行为是可以预料的。