【问题标题】:Pl/SQL Bulk Migration of some columns某些列的 Pl/SQL 批量迁移
【发布时间】:2013-08-30 09:06:25
【问题描述】:

我知道有很多批量插入脚本,因为我是 pl/sql 的新手,所以我很困惑。 我有两个表 TABLEA(id,name,sirname,age) TABLEB(id,age),我想将所有数据从 TABLEB 迁移到 TABLEA。

我找到了一个链接http://psoug.org/reference/array_processing.html,其中“FORALL Insert”解释了如何执行此操作。但它假设两个表列类型相同。但就我而言,我将复制到 TABLEA 上的某些列。

由于 TABLEB 有 3000 万的记录,因此性能很重要。 我想说的另一件事是 TABLEB 是外部表,我的意思是它是从 txt 文件将适当的列映射到表中创建的。

那么可以做些什么来为我的案例修改以下脚本。

CREATE TABLE servers2 AS
SELECT *
FROM servers
WHERE 1=2;

DECLARE
 CURSOR s_cur IS
 SELECT *
 FROM servers;

 TYPE fetch_array IS TABLE OF s_cur%ROWTYPE;
 s_array fetch_array;
BEGIN
  OPEN s_cur;
  LOOP
    FETCH s_cur BULK COLLECT INTO s_array LIMIT 1000;

    FORALL i IN 1..s_array.COUNT
    INSERT INTO servers2 VALUES s_array(i);

    EXIT WHEN s_cur%NOTFOUND;
  END LOOP;
  CLOSE s_cur;
  COMMIT;
END;

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    可能最快的方法是使用带有 APPEND 提示的普通旧 INSERT:

     INSERT /*+APPEND*/ INTO table_a(id,age)
      SELECT id, age
      FROM table_b;
    

    不需要 FORALL / BULK COLLECT 等。

    【讨论】:

    • 绝对是更好的方法。
    • 我有两个问题,首先我必须调整限制,因为我有 30M 数据,其次如果 table_a 不为空并且它与 table_b 有共同的数据,这违反了主键约束。在这种情况下有没有办法忽略元组。
    • @mmc18 #1 否(30MB 数据不多)。 #2 超出了这个问题的范围(提示:见merge)!
    • 如果只是忽略存在主键违规的新行,而不是将表更新为新值,那么只需使用 NOT EXISTS 相关子查询或 LEFT JOIN。跨度>
    • 只是要添加,如果您重复从 tablea 添加和删除行,然后使用 APPEND 插入其中会在表中留下一些空或部分空的块。您可以通过不使用 APPEND 或在插入之前合并表,或者将数据复制到其他地方并截断表,然后在一次插入中插入旧数据和新数据来处理这个问题。
    【解决方案2】:

    您不必为外部表更改任何内容。由于您有 30M 数据,因此您可能可以将限制增加到 100000。但这完全取决于您的数据库设计以及您拥有多少流量。但我更喜欢增加限制。

    【讨论】:

    • 不,完全忘记限制和 PL/SQL 游标。这是 SQL 的工作。
    • 3000 万行是巨大的数据。执行单次插入可能需要时间并导致快照太旧错误。我更喜欢 PL/SQL 块。
    • 恐怕我不同意这一切。 3000 万行应该是一个微不足道的单个 SQL 插入,这将比基于 PL/SQL 的方法更快、更高效。 snapshot-too-old 错误不太可能发生,尤其是使用外部表作为数据源和直接路径插入时,因为查询几乎不需要从 UNDO 数据重建块。
    • 我在回答时尽量记住外部表。感谢您指出。
    猜你喜欢
    • 2016-09-17
    • 1970-01-01
    • 2012-07-27
    • 2012-08-06
    • 1970-01-01
    • 2011-07-17
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多