我目前正在实施监控数据到HDFS和Hive表的ETL(Talend)。 我现在面临重复的问题。更详细的说,如果我们需要使用相同的输入运行一次ETL作业2次,我们最终会在Hive表中找到重复项。
RDMS中的解决方案是将输入文件名存储到" DELETE WHERE文件名= ..."在发送数据之前。但是Hive不是RDBMS,并且不支持删除。
我想就如何处理这个问题提出建议。我设想了两个解决方案:
如果您有任何其他解决方案,请随意提出建议。
贝斯茨, 奥兰多
答案 0 :(得分:0)
如果目标表中的数据量不太大,我建议
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
命令增加),性能将是最佳,但你可以肯定你不会有任何重复。
在您的实际使用案例中,您不必检查每个密钥,而只需检查&#34;批次ID&#34;,更准确地说是原始文件名;我在以前的工作中完成它的方式是
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是一种列式格式,因此它是重要的不同值的数量 - 因此开销会保持较低。
请注意明确的&#34; DISTINCT&#34;在子查询中;一个成熟的DBMS优化器会在执行时自动执行它,但Hive不会(还没有)所以你必须强制它。另请注意&#34; 1&#34;只是因为&#34; SELECT&#34;所需的虚拟值。语义;再一次,一个成熟的DBMS将允许一个虚拟&#34; null&#34;但某些版本的Hive会崩溃(例如在V0.14中使用Tez)所以&#34; 1&#34;或&#34;&#39; A&#39;&#34;更安全。
参考:
答案 1 :(得分:0)
谢谢大家的帮助。
干杯, 奥兰多