更改表中的 2 列 - 有风险的操作吗?

发布于 2024-09-30 20:46:55 字数 182 浏览 1 评论 0原文

我在 MSSQL Server 2005 上有一个包含约 100 列、约 30M 行的表。

我需要更改 2 列 - 将它们的类型从 VARCHAR(1024) 更改为 VARCHAR(max)。这些列没有索引。

我担心这样做会填满日志,并导致操作失败。如何估计此类操作所需的可用磁盘空间(数据和日志)以确保其不会失败?

I have a table with ~100 columns, about ~30M rows, on MSSQL server 2005.

I need to alter 2 columns - change their types from VARCHAR(1024) to VARCHAR(max). These columns does not have index on them.

I'm worried that doing so will fill up the log, and cause the operation to fail. How can I estimate the needed free disk space, both of the data and the log, needed for such operation to ensure it will not fail?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

香橙ぽ 2024-10-07 20:46:55

你是对的,增加列大小(包括到 MAX)将为大型表生成巨大的日志,因为每一行都将被更新(在幕后旧列被删除,新列被添加并复制数据)。

  1. 添加 VARCHAR(MAX) NULL 类型的新列。作为可为空的列,将仅添加为元数据(无数据更新)
  2. 将数据从旧列复制到新列。可以分批进行,缓解日志压力。
  3. 删除旧的列。这将是仅元数据的操作。
  4. 使用 sp_rename 将新列重命名为旧的列名称。
  5. 稍后,在您方便的时候,重建聚集索引(如果需要,可以在线重建)以摆脱旧列占用的空间。

这样您就可以通过在步骤 2)中控制批次来控制日志。您还可以通过不将整个表复制到新表中来最大程度地减少对权限、约束和关系的破坏(SSMS 做得很差......)。

您可以同时对两列执行此顺序。

You are right, increasing the column size (including to MAX) will generate a huge log for a large table, because every row will be updated (behind the scenens the old column gets dropped and a new column gets added and data is copied).

  1. Add a new column of type VARCHAR(MAX) NULL. As a nullable column, will be added as metadata only (no data update)
  2. Copy the data from the old column to new column. This can be done in batches to alleviate the log pressure.
  3. Drop the old column. This will be a metadata only operation.
  4. Use sp_rename to rename the new column to the old column name.
  5. Later, at your convenience, rebuild the clustered index (online if needed) to get rid of the space occupied by the old column

This way you get control over the log by controlling the batches at step 2). You also minimize the disruption on permissions, constraints and relations by not copying the entire table into a new one (as SSMS so poorly does...).

You can do this sequence for both columns at once.

孤单情人 2024-10-07 20:46:55

我建议您考虑:

  1. 使用新模式创建一个新表
  2. 将数据从旧表复制到新表
  3. 删除旧表
  4. 将新表重命名为旧表的名称

这可能是一个成本低得多的操作,可以通过以下方式完成使用 INSERT/SELECT 进行最少的日志记录(如果是 SQL Server 2008 或更高版本)。

I would recommend that you consider, instead:

  1. Create a new table with the new schema
  2. Copy data from old table to new table
  3. Drop old table
  4. Rename new table to name of old table

This might be a far less costly operation and could possibly be done with minimal logging using INSERT/SELECT (if this were SQL Server 2008 or higher).

晨光如昨 2024-10-07 20:46:55

为什么增加 VARCHAR 限制会填满日志?

Why would increasing the VARCHAR limit fill up the log?

作妖 2024-10-07 20:46:55

尝试以较小的片段进行一些测试。我的意思是,您可以在本地创建具有几千行的相同结构,并查看前后的差异。我认为变化将是线性的。真正的问题是关于重做日志,它是否适合它,因为您可以立即完成它。必须在网上做,还是可以暂时停止生产?如果你可以停止,也许有一种方法可以像 Oracle 一样停止 MSSQL 中的重做日志。它可以让它变得更快。如果你需要在线完成,你可以尝试创建一个新列,将值循环复制到其中,例如一次复制100000行,提交,继续。完成后,也许删除原始列并重命名新列比更改更快。

Try to do some test in smaller pieces. I mean, you could create the same structure locally with few thousand rows, and see the difference before and after. I think the change will be linear. The real question is about redo log, if it will fit into it or not, since you can do it at once. Must you do it online, or you can stop production for a while? If you can stop, maybe there is a way to stop redo log in MSSQL like in Oracle. It could make it a lot faster. If you need to do it online, you could try to make a new column, copy the value into it by a cycle for example 100000 rows at once, commit, continue. After completing maybe to drop original column and rename new one is faster than altering.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文