【问题标题】:Set ORC file name设置 ORC 文件名
【发布时间】:2016-02-18 15:49:02
【问题描述】:

我目前正在实施对 HDFS 和 Hive 表的监控数据的 ETL (Talend)。 我现在面临重复的问题。更详细地说,如果我们需要使用相同的输入运行一个 ETL 作业 2 次,我们最终会在 Hive 表中出现重复。

RDMS 中的解决方案是在发送数据之前存储输入文件名并“删除其中文件名=...”。但 Hive 不是 RDBMS,不支持删除。

我想就如何处理这个问题获得您的建议。我设想了两种解决方案:

  • 实际上,ETL 正在将 CSV 文件放入 HDFS,这些文件用于为 ORC 表提供“INSERT INTO TABLE ... SELECT ...” 问题是,通过这个操作,我输了文件名,ORC文件名为00000。是否可以指定这个创建的ORC文件的文件名?如果可以,我可以通过文件名搜索数据并删除在启动 ETL 之前。
  • 我不习惯 Hive 的 ACID 功能(Hive 0.14+ 上的功能)。 您会建议使用 Hive 启用 ACID 吗?我可以使用它“删除 WHERE”吗?

如果您对此有任何其他解决方案,请随时提出建议。

最好的, 奥兰多

【问题讨论】:

  • 如何将所有文件加载到临时表中并使用 INSERT OVERWRITE ... SELECT DISTINCT.. 加载最终表。
  • 通过这样做,我确实可以避免每次运行 ETL 时出现重复,但我无法避免使用相同输入的 2 次运行出现重复。此外,如果多个输入文件存储在同一个分区中,则 INSERT OVERWRITE 会导致数据丢失。

标签: hadoop hive etl


【解决方案1】:

如果目标表的数据量不要太大,我会建议

INSERT INTO TABLE trg
SELECT ... FROM src
WHERE NOT EXISTS
 (SELECT 1
  FROM trg x
  WHERE x.key =src.key
    AND <<additional filter on target to reduce data volume>> 
 )

Hive 会自动将相关子查询重写为 MapJoin,将目标表中的所有候选键提取到 Java HashMap 中,并即时过滤源行。只要 HashMap 可以适合 Mappers 堆大小的可用 RAM(检查您的默认 conf 文件,必要时在 Hive 脚本中使用set 命令增加)性能将是次优的,但你可以很确定你不会有任何重复。

并且在您的实际用例中您不必检查每个键,只需检查“批次 ID”,更准确地说是原始文件名;我在上一份工作中的做法是

INSERT INTO TABLE trg
SELECT ..., INPUT__FILE__NAME as original_file_name
FROM src
WHERE NOT EXISTS
 (SELECT DISTINCT 1
  FROM trg x
  WHERE x.INPUT__FILE__NAME =src.original_file_name
    AND <<additional filter on target to reduce data volume>> 
 )

这意味着您的目标表中有一个额外的列,但由于 ORC 是一种列格式,因此重要的是不同值的数量 -- 这样开销就会保持在较低水平。

注意子查询中显式的“DISTINCT”;成熟的 DBMS 优化器会在执行时自动执行此操作,但 Hive 不会(还没有)因此您必须强制执行。另请注意,“1”只是由于“SELECT”语义而需要的虚拟值;同样,成熟的 DBMS 将允许虚拟“null”,但某些版本的 Hive 会崩溃(例如,在 V0.14 中使用 Tez),因此“1”或“'A'”更安全。

参考:

【讨论】:

  • 嗨,Samson,感谢您提供如此明确的答案。我确实认为是这样的解决方案。我的桌子不是很大(每年约 500 人)。但是我仍然怀疑这个解决方案的性能:它是否意味着将所有数据暂时存储在这个表中两次?
  • 除了文件名之外没有任何东西可以存储。每次都扫描表,以获取键列表。 ORC 的好处是 I/O 将仅限于条带页脚 (检查是否满足 > - 例如“插入日期不超过 1 个月”与在该条带中插入日期的最小/最大值) 然后到匹配条带的内容,仅关注键列。这不是完整扫描。
  • 好的,谢谢您的澄清。那么 Hive 的 ACID 能力呢?由于我会将文件名存储在表中,因此 DELETE WHERE 文件名 = .. 会导致 FULL SCAN 吗?
  • 由于 HDFS 使用 immutable 文件(好的,现在有例外,但它们对 Hive 无关紧要)DELETE 将意味着 create-a-copy-of-the -没有这些记录的原始文件并替换原始文件。立即或稍后(事务模式需要在 HDFS 级别进行垃圾收集的后台进程)。我从未听过任何关于这方面的热情报道。它只是一个创可贴,主要针对需要微批量插入(例如使用 Flume)的人,其中定期背景压缩是有意义的。
  • 非常感谢您对此的反馈。这真的很有帮助。我将寻求您的解决方案或更改我的表分区以允许删除整个分区。再次感谢。
【解决方案2】:

我在回答自己。我找到了一个解决方案: 我使用 (date,input_file_name) 对表进行了分区(注意,我可以在 Hive 中使用 SELECT INPUT__FILE__NAME 获取 input_file_name。 一旦我这样做了,在运行 ETL 之前,我可以向 Hive 发送一个 ALTER TABLE DROP IF EXISTS PARTITION (file_name=...) 以便如果这个 INPUT_FILE 已经发送到 ORC 表,则删除包含输入数据的文件夹.

感谢大家的帮助。

干杯, 奥兰多

【讨论】:

    猜你喜欢
    • 2020-03-02
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    相关资源
    最近更新 更多