从多个服务器加载数据时避免数据重复

js4nwp54  于 2021-06-03  发布在  Hadoop
关注(0)|答案(2)|浏览(314)

我有十几个网络服务器,每个服务器都将数据写入日志文件。在每小时开始时,使用运行以下命令的cron脚本将前一小时的数据加载到配置单元:

hive -e "LOAD DATA LOCAL INPATH 'myfile.log' INTO TABLE my_table PARTITION(dt='2015-08-17-05')"

在某些情况下,命令失败并退出,代码不是0,在这种情况下,脚本将等待并重试。问题是,在某些失败的情况下,数据加载不会失败,即使它显示失败消息。如何确定数据是否已加载?
加载数据的“故障”示例:
将数据加载到表default.my_表分区(dt=2015-08-17-05)失败,出现异常org.apache.hadoop.hive.ql.metadata.hiveexception:无法更改分区。失败:执行错误,从org.apache.hadoop.hive.ql.exec.movetask返回代码1
编辑:或者,有没有一种方法可以查询配置单元中加载的文件名?我可以用 DESCRIBE 查看文件数。我能知道他们的名字吗?

qq24tv8q

qq24tv8q1#

我不相信你能在hadoop/hive中简单地做到这一点。下面是python实现的基础知识:

import subprocess
x=subprocess.check_output([hive -e "select count(*) from my_table where dt='2015-08-17-05'"])
print type(x)
print x

但是您必须花一些时间使用反斜杠才能使hive-e使用python。这可能非常困难。先用简单的查询编写一个文件,然后使用 hive -f filename . 然后,打印 subprocess.check_output 以便查看输出是如何存储的。您可能需要进行一些正则表达式或类型转换,但我认为它应该作为字符串返回。然后简单地使用if语句:

if x > 0:
    pass
else:
    hive -e "LOAD DATA LOCAL INPATH 'myfile.log' INTO TABLE my_table PARTITION(dt='2015-08-17-05')"
y4ekin9u

y4ekin9u2#

关于“分区中加载了哪些文件”:
如果你用过 EXTERNAL TABLE 把你的原始数据文件上传到 LOCATION ,那么你可以
(a) 跑一趟就行了 hdfs dfs -ls 在该目录上从命令行(或使用等效的javaapi调用)运行一个配置单元查询,如 select distinct INPUT__FILE__NAME from (...) 但是在您的例子中,您将数据复制到一个“托管”表中,因此无法检索数据沿袭(即,哪个日志文件用于创建每个托管数据文件)
…当然,除非您在日志文件中显式地添加原始文件名(在“特殊”头记录上,或者在每个记录的开头-这可以使用好的旧文件来完成) sed )
关于“如何自动避免插入时的重复”:有一种方法,但它需要相当多的重新设计,并且会花费您的处理时间/(额外的Map步骤加上Map连接)/。。。
将日志文件Map到 EXTERNAL TABLE 以便运行insert select查询
使用将原始文件名上载到托管表中 INPUT__FILE__NAME 伪列作为源
添加 WHERE NOT EXISTS 子句w/相关子查询,这样,如果源文件名已存在于目标中,则不加载任何内容 INSERT INTO TABLE Target SELECT ColA, ColB, ColC, INPUT__FILE__NAME AS SrcFileName FROM Source src WHERE NOT EXISTS (SELECT DISTINCT 1 FROM Target trg WHERE trg.SrcFileName =src.INPUT__FILE__NAME ) 注意这个愚蠢的区别,实际上是需要避免吹走你的Map器内存;对于像oracle这样成熟的dbms来说,这是没有用的,但是hive优化器仍然相当粗糙。。。

相关问题