我有这个业务需求,我们需要将数据从Hadoop导出到Oracle,因为sqoop无法有效处理以覆盖模式导出的删除操作。为了保持最短的停机时间,我们开发了一个流程(写为存储过程),该流程按顺序执行以下步骤:

创建了STG_TABLES(作为登台表)和FINAL_TABLES。

一旦sqoop将数据导出到stg_tables。

  • 存储过程将final_tables重命名(假设我们上次运行的final_tables中有数据)重命名为temp_tables
  • 存储过程将stg_tables重命名为final_tables
  • 存储过程将temp_tables重命名为stg_tables并被截断(使它们为下一次新导出做好准备)。

  • 您是否有更好的想法/建议来改进上述过程?

    请提出建议。

    谢谢!

    最佳答案

    根据需要定义FINAL表,并添加一个技术列load_dateDATE类型。

    例:

    create table FINAL_TABLES
    (load_date DATE,
    col1 varchar2(10));
    

    使用 STG 定义具有相同结构的interval partitioning
    create table STG_TABLES
    (load_date DATE,
    col1 varchar2(10))
       PARTITION BY RANGE (load_date)
       INTERVAL(NUMTODSINTERVAL(1, 'DAY'))
    (
      PARTITION p_init VALUES LESS THAN (TO_DATE('15-03-2020', 'DD-MM-YYYY'))
    );
    

    现在,执行sqoop装载填充STG表中的数据。 load_date是加载的时间戳,在所有行中均相等。

    使用insert模拟的示例
    insert into STG_TABLES (load_date, col1)
    values (sysdate,'new load');
    commit;
    

    在下一步中,使用STG交换FINALexchange partition表的内容
    alter table STG_TABLES
    exchange partition FOR (to_date('2020-03-15 05:55:00','yyyy-mm-dd hh24:mi:ss'))
    with table FINAL_TABLES
    without validation;
    
    STG表的分区由当前load_date值标识

    现在,已加载的数据在FILNAL表中,并且STG表包含FINAL表的先前状态。

    您可以通过删除分区来摆脱它,可以在下一次加载之前立即完成。后一个选项可以帮助进行故障排除。
    alter table STG_TABLES
    drop partition FOR (to_date('2020-03-15 05:55:00','yyyy-mm-dd hh24:mi:ss'));
    

    最后说明
  • 此步骤的性能与重命名表(仅数据字典 Activity )的解决方案相当。对于FINAL表的使用者而言,此选项要好得多,因为该表一直存在,因此查询不会因RENAME而无效。

    如果在下一次加载之前推迟DROP PARTITION,则即使在加载期间长时间运行的查询也可以保留下来,并在STG表的各段上继续进行。
  • 如果FINAL表具有索引,则在STG上将相同的索引结构定义为LOCAL索引。

    加载后检查STG表是否所有索引均有效

    INCLUDING INDEXES添加到交换分区语句。
  • 上面描述的模式定义了完整的刷新负载,即旧状态被新状态完全覆盖。您可以对增量负载使用相同的机制,即将新负载添加到当前状态。

    简单定义未分区的STG表和已分区的FINAL表。

  • 上面的示例每天可处理一次增量负载-针对不同的频率调整INTERVAL模式。

    08-25 04:18