我目前正在将监视数据的etl(talend)实现到hdfs和hive表。我现在面临着对复制品的担忧。更详细地说,如果我们需要用相同的输入运行一个etl作业两次,那么我们的配置单元表中就会出现重复的作业。
在rdms中解决这个问题的方法是存储输入文件名,并在发送数据之前“删除其中的文件名=…”。但是hive不是rdbms,不支持删除。
我想听听你对如何处理这件事的建议。我设想了两种解决方案:
实际上,etl将csv文件放入hdfs,用于向orc表提供“insert into table…”。。。选择…“问题是,在这个操作中,我丢失了文件名,orc文件名为00000。是否可以指定此创建的orc文件的文件名?如果是的话,我可以通过文件名搜索数据,并在启动etl之前删除它。
我不习惯Hive的酸性功能(Hive0.14+上的功能)。你会推荐用Hive启用acid吗?我能用它“删除哪里”吗?
如果你有其他的解决办法,请随时提出。
最佳,奥兰多
2条答案
按热度按时间ldxq2e6h1#
我在回答我自己。我找到了一个解决方案:我用(date,input\u file\u name)划分了我的表(注意,我可以通过在hive中选择input\u file\u name来获取输入的\u file\u name)。一旦我这样做了,在运行etl之前,我可以向hive发送alter table drop if exists分区(文件名=…),这样,如果这个输入文件已经发送到orc表,那么包含输入数据的文件夹就会被删除。
谢谢大家的帮助。
干杯,奥兰多
nsc4cvqm2#
如果目标表中的数据量不是太大,我建议
hive将自动将相关子查询重写为mapjoin,将目标表中的所有候选键提取为javahashmap,并动态过滤源行。只要hashmap可以容纳ram中可用的mappers堆大小(检查您的默认conf文件,增加一个
set
命令)性能将是次优的,但您可以非常确定不会有任何重复。在您的实际用例中,您不必检查每个键,只需检查一个“批id”,更准确地说是原始文件名;我以前的工作方式是
这意味着您的目标表中有一个额外的列,但是由于orc是一种列格式,所以重要的是不同值的数量——这样开销就会保持在较低的水平。
注意子查询中显式的“distinct”;一个成熟的dbms优化器会在执行时自动执行,但是hive没有(还没有),所以您必须强制执行它。注意“1”只是一个伪值,因为“select”语义是必需的;同样,一个成熟的dbms会允许一个虚拟的“null”,但是有些版本的hive会崩溃(例如v0.14中的tez),所以“1”或“a”更安全。
参考文献:
https://cwiki.apache.org/confluence/display/hive/languagemanual+subqueries#languagemanualsubqueries-WHERE子句中的子查询
https://cwiki.apache.org/confluence/display/hive/languagemanual+virtualcolumns