sql - 更新大型表的主表和子表的主键

标签 sql sql-server oracle migration mysql4

我有一个相当大的数据库,其中一个主表以单列 GUID(自定义 GUID 类似算法)作为主键,还有 8 个与该 GUID 列具有外键关系的子表。所有表大约有 3-8 百万条记录。这些表都没有任何 BLOB/CLOB/TEXT 或任何其他奇特的数据类型,只有普通数字、varchar、日期和时间戳(每个表中大约有 15-45 列)。除主外键外,没有分区或其他索引。

现在,自定义 GUID 算法已更改,尽管没有冲突,但我想迁移所有旧数据以使用通过新算法生成的 GUID。无需更改其他列。第一要务是数据完整性,性能是次要的。

我能想到的一些可能的解决方案是(你可能会注意到它们都只围绕一个想法)

  1. 添加新列 ngu_id 并填充新的 gu_id;禁用约束;将 ngu_id 更新为 gu_id 的子表;重命名 ngu_id->gu_id;重新启用约束
  2. 从子表中读取一条主记录及其从属子记录;使用新的 gu_id 插入到同一个表中;删除所有具有旧 gu_ids 的记录
  3. 删除约束;向主表添加触发器,以便更新所有子表;开始用新的 gu_id 更新旧的 gu_id;重新启用约束
  4. 为主表添加触发器,以便更新所有子表;开始用新的 gu_id 更新旧的 gu_id
  5. 在所有主表和子表上创建新列ngu_ids;在 ngu_id 列上创建外键约束;主表添加更新触发器,将值级联到子表;将新的 gu_id 值插入 ngu_id 列;删除基于 gu_id 的旧外键约束;删除 gu_id 列并将 ngu_id 重命名为 gu_id;如有必要,重新创建约束;
  6. 如果可用,请使用更新级联

我的问题是:

  1. 有更好的方法吗? (不能把头埋进沙子里,必须这么做)
  2. 最合适的方法是什么? (我必须在 Oracle、SQL Server 和 mysql4 中执行此操作,因此欢迎特定于供应商的 hack)
  3. 此类练习的典型失败点是什么以及如何最大限度地减少这些失败点?

如果您到目前为止一直支持我,谢谢您并希望您能提供帮助:)

最佳答案

你的想法应该可行。第一种可能是我会使用的方式。执行此操作时需要考虑的一些注意事项和事项:
除非您有当前备份,否则请勿执行此操作。
我会将这两个值保留在主表中。这样,如果您需要从一些旧的文书工作中找出您需要访问哪些记录,您就可以做到。 执行此操作时,请关闭数据库进行维护并将其置于单用户模式。在执行此类操作时,您最不需要的就是用户在您处于中途时尝试进行更改。当然,进入单用户模式后的第一个操作就是上述备份。您可能应该将停机时间安排在使用量最轻的时候。 首先在开发上进行测试!这还应该让您了解需要关闭生产多长时间。另外,您可以尝试多种方法,看看哪种方法最快。
请务必提前告知用户,数据库将在计划的维护时间关闭,以及何时可以再次可用。确保时机没问题。当他们计划熬夜运行季度报告而数据库不可用而他们却不知道时,这真的让人很生气。
有相当多的记录,您可能希望批量运行子表的更新(不使用级联更新的原因之一)。这比尝试通过一次更新更新 500 万条记录要快。但是,不要尝试一次更新一条记录,否则明年您仍将在这里执行此任务。
删除所有表中 GUID 字段上的索引,并在完成后重新创建。这应该会提高变更的性能。

关于sql - 更新大型表的主表和子表的主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/306433/

相关文章:

sql - 如何使此 SQL 任务更快地完成

oracle - Golden Gate 复制极度延迟

Oracle 向下舍入

c# - 如何使用 Entity Framework 使用序列在 Oracle 中插入标识值

mysql:仅当表存在时才更改表名

mysql - 获取每个人每天的最短日期时间的记录

mysql - 在创建 SQL 语句时需要帮助

sql - 我怎样才能只得到一个数字的第一位小数而不四舍五入

mysql - SQL平均每天花钱

c# - 在 ASP.NET Web 应用程序中将架构名称添加到 SQL 表名称