【问题标题】:SQL Update large tableSQL 更新大表
【发布时间】:2016-04-26 05:21:34
【问题描述】:

我有一个问题。我需要更新两个大表 - t_contact(1.7 亿行)和t_participants(1100 万行)。此表都有CUSTOMER_ID 列。其中一些 ID 错误,我需要更新它。错误的 ID 大约是 14 万。 我知道如果我要使用UPDATE TABLE 需要很多次,但是这两个表一定不能长时间不可用。我该怎么办?

【问题讨论】:

  • 你怎么知道什么是错误的id?
  • A 有一个表 t_wrong_ids,它有两列:OLD_ID、NEW_ID。 OLD_ID - 原始正确 ID,NEW_ID - 位于我的大表中的错误 ID。
  • 一种典型的方法是批量更新,一次更改 100 或 1000 行。

标签: sql oracle merge sql-update bigdata


【解决方案1】:
declare
  i number := 0;
  cursor s1 is SELECT rowid, t.* FROM table_name  t WHERE column_name =x;
begin
  for c1 in s1 loop
      UPDATE table_name SET column_name = y
             where rowid = c1.rowid;
      i := i + 1;              -- Commit after every X records
      if i > 50000 then
         commit;
         i := 0;
      end if;
  end loop;
  commit;
end;
/

【讨论】:

    【解决方案2】:

    如果您在应该使用合并的地方存储了错误的 ID:

    MERGE INTO t_contact D
    USING (select * from t_wrong_ids) S
    ON (D.CUSTOMER_ID = S.NEW_ID)
    WHEN MATCHED THEN UPDATE SET D.CUSTOMER_ID = S.OLD_ID
    

    比普通更新快很多。

    第二张表相同:

    MERGE INTO t_participants D
    USING (select * from t_wrong_ids) S
    ON (D.CUSTOMER_ID = S.NEW_ID)
    WHEN MATCHED THEN UPDATE SET D.CUSTOMER_ID = S.OLD_ID
    

    【讨论】:

    • 但是如果 t_contact 有 1.7 亿行...需要多长时间?
    • 1.7 亿条记录并不能说明什么,取决于数据、列等。我真的无法告诉你。你认为什么是好时机?无论如何,这应该是最快的方式
    • 但是如果我复制这个表然后更新 ID 并最后用原始表更改这个更新的表?我原来的表 t_contact 真的必须几乎总是可用
    • 嗯,是的,您可以复制表更新它,然后用旧表替换它。如果查看更新,合并就是您要查找的内容
    • 好的,我应该如何交换这张桌子。我知道第一步将是:CREATE TEMP_T AS SELECT * FROM T_CONTACTS。然后将我的临时表与 t_wrong_ids 合并,但是如何将这个临时表交换回来?
    【解决方案3】:

    将您的一张表拆分为多个部分,并在 PL/SQL 块中一一处理。例如,假设 ID 是随之而来的,您将 t_participants 拆分为多个部分,每个部分包含 100 万行:

    begin
      -- 1 and 11 - hardcoded values, 
      -- since your t_participants table has 11 000 000 rows
      for i in 1..11 loop 
        merge t_contact c
        using (select * from t_participants 
               where id between (i - 1) * 1000000 and i * 1000000) p
           on (c.id = p.id)
         when matched then update ...;
      commit;
      end loop;
    end;
    

    我选择了 1000000 条记录的大小,但您可以选择其他大小。这将取决于您的服务器性能。尝试手动更新 100、1000、10000 等行,以定义最方便的大小。

    【讨论】:

    • 那是不必要的,因为他有错误 id 的表
    • @sagi 这只是部分更新的一般想法。链接条件on (c.id = p.id) 可以替换为on (c.correct_id = p.correct_id) 或其他任何内容。
    猜你喜欢
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多