1

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

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

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

  1. 添加新列 ngu_id 并使用新的 gu_id 填充;禁用约束;用 ngu_id 作为 gu_id 更新子表;重命名 ngu_id->gu_id;重新启用约束
  2. 从子表中读取一个主记录及其从属子记录;用新的 gu_id 插入同一张表;删除所有旧 gu_id 的记录
  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. 如果可用,使用on update cascade

我的问题是:

  1. 有没有更好的办法?(不能把我的头埋在沙子里,必须这样做)
  2. 最合适的方法是什么?(我必须在 Oracle、SQL server 和 mysql4 中执行此操作,因此欢迎使用特定于供应商的 hack)
  3. 这种练习的典型失败点是什么以及如何将它们最小化?

如果你到目前为止和我在一起,谢谢你,希望你能帮助:)

4

4 回答 4

3

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

于 2008-11-20T19:13:01.367 回答
0

创建一个新表,其中包含旧的和新的 pk 值。在两列上放置唯一的约束,以确保您到目前为止没有破坏任何东西。

禁用约束。

对所有表运行更新以将旧值修改为新值。

启用 PK,然后启用 FK。

于 2008-11-20T20:03:29.157 回答
0

很难说“最佳”或“最合适”的方法是什么,因为您没有描述您在解决方案中寻找什么。例如,当您迁移到新 ID 时,这些表是否需要可供查询?它们是否需要可用于并发修改?尽快完成迁移是否重要?最小化用于迁移的空间是否重要?

话虽如此,假设它们都满足您的要求,我更喜欢#1而不是您的其他想法。

任何涉及更新子表的触发器似乎都容易出错且过于复杂,并且可能不会像#1那样执行。

假设新 ID 永远不会与旧 ID 冲突是否安全?如果没有,基于一次更新一个 ID 的解决方案将不得不担心冲突——这会很快变得混乱。

您是否考虑过使用CREATE TABLE AS SELECT(CTAS) 使用新 ID 填充新表?您将制作现有表的副本,这将需要额外的空间,但它可能比更新现有表更快。想法是:(i) 使用 CTAS 创建具有新 ID 的新表来代替旧表,(ii) 在新表上创建适当的索引和约束,(iii) 删除旧表,(iv) 重命名新表旧名称的表。

于 2008-11-22T00:14:52.833 回答
0

实际上,这取决于您的 RDBMS。

使用 Oracle,最简单的选择是使所有外键约束“延迟”(提交时检查),在单个事务中执行更新,然后提交。

于 2008-11-22T01:04:06.557 回答