我有十几个网络服务器,每个服务器都将数据写入日志文件。在每小时开始时,使用运行以下命令的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
查看文件数。我能知道他们的名字吗?
2条答案
按热度按时间qq24tv8q1#
我不相信你能在hadoop/hive中简单地做到这一点。下面是python实现的基础知识:
但是您必须花一些时间使用反斜杠才能使hive-e使用python。这可能非常困难。先用简单的查询编写一个文件,然后使用
hive -f filename
. 然后,打印subprocess.check_output
以便查看输出是如何存储的。您可能需要进行一些正则表达式或类型转换,但我认为它应该作为字符串返回。然后简单地使用if语句: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优化器仍然相当粗糙。。。