Apache Hive 未正确返回 YARN 应用程序结果
Apache Hive Not Returning YARN Application Results Correctly
我是 运行 AWS EC2 上的一个全新集群。我有一个用 S3 上的数据定义的外部 table(分区)。我能够查询此 table 并使用简单的 select * 语句将结果接收到控制台:
hive> set hive.execution.engine=tez;
hive> select * from external_table where partition_1='1' and partition_2='2';
<correct results returned>
运行 需要 Tez 的查询不会 return 将结果发送到控制台:
hive> set hive.execution.engine=tez;
hive> select count(*) from external_table where partition_1='1' and partition_2='2';
Status: Running (Executing on YARN cluster with App id application_1572972524483_0012)
OK
+------+
| _c0 |
+------+
+------+
No rows selected (8.902 seconds)
但是,如果我深入挖掘日志和文件系统,我可以找到该查询的结果:
(yarn.resourcemanager.log) org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root OPERATION=AM Released Container TARGET=SchedulerApp RESULT=SUCCESS APPID=application_1572972524483_0022 CONTAINERID=container_1572972524483_0022_01_000002 RESOURCE=<memory:1024, vCores:1> QUEUENAME=default
(container_folder/syslog_attempt) [TezChild] |exec.FileSinkOperator|: New Final Path: FS file:/tmp/<REALLY LONG FILE PATH>/000000_0
[root #] cat /tmp/<REALLY LONG FILE PATH>/000000_0
SEQ"org.apache.hadoop.io.BytesWritableorg.apache.hadoop.io.Textl▒ꩇ1som}▒▒j¹▒ 2060
2060 是分区的正确计数。
现在,奇怪的是,如果我在 HDFS 上插入覆盖目录,我能够从应用程序中获取结果:
hive> set hive.execution.engine=tez;
hive> INSERT OVERWRITE DIRECTORY '/tmp/local_out' select count(*) from external_table where partition_1='1' and partition_2='2';
[root #] hdfs dfs -cat /tmp/local_out/000000_0
2060
但是,尝试插入覆盖本地目录失败:
hive> set hive.execution.engine=tez;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' select count(*) from external_table where partition_1='1' and partition_2='2';
[root #] cat /tmp/local_out/000000_0
cat: /tmp/local_out/000000_0: No such file or directory
如果我为这个查询 cat 容器结果文件,它只是数字,没有 class 名称或特殊字符:
[root #] cat /tmp/<REALLY LONG FILE PATH>/000000_0
2060
我能找到的唯一不合适的日志消息来自 YARN ResourceManager 日志:
(yarn.resourcemanager.log) INFO org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root OPERATION=AM Released Container TARGET=SchedulerApp RESULT=SUCCESS APPID=application_1572972524483_0023 CONTAINERID=container_1572972524483_0023_01_000004 RESOURCE=<memory:1024, vCores:1> QUEUENAME=default
(yarn.resourcemanager.log) WARN org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root IP=NMIP OPERATION=AM Released Container TARGET=Scheduler RESULT=FAILURE DESCRIPTION=Trying to release container not owned by app or with invalid id. PERMISSIONS=Unauthorized access or invalid container APPID=application_1572972524483_0023 CONTAINERID=container_1572972524483_0023_01_000004
基于最模糊的印象,我的猜测是当结果写入本地文件系统时存在字符编码问题(因此容器结果文件中的特殊字符)但这实际上只是一个猜测,我不知道如何verify/tackle那个问题。非常感谢任何帮助!
你是如何将数据插入到配置单元中的table? Hive 从 Metastore 而不是 运行 给出 count(*) 结果一个计数作业来优化性能。首先尝试在此 table 上进行 MSCK 修复,让配置单元了解新的外部文件并相应地修改配置单元元存储。
Apache Hive 邮件列表中的某个人建议这是由 YARN 容器将其结果文件写入本地机器 运行 而不是 HDFS 引起的。我在源代码中做了一些挖掘,发现:
mapreduce.framework.name=local
这是 Hadoop 3.2.1 中的默认设置,导致了这个问题。
解决方法:
set mapreduce.framework.name=yarn
我是 运行 AWS EC2 上的一个全新集群。我有一个用 S3 上的数据定义的外部 table(分区)。我能够查询此 table 并使用简单的 select * 语句将结果接收到控制台:
hive> set hive.execution.engine=tez;
hive> select * from external_table where partition_1='1' and partition_2='2';
<correct results returned>
运行 需要 Tez 的查询不会 return 将结果发送到控制台:
hive> set hive.execution.engine=tez;
hive> select count(*) from external_table where partition_1='1' and partition_2='2';
Status: Running (Executing on YARN cluster with App id application_1572972524483_0012)
OK
+------+
| _c0 |
+------+
+------+
No rows selected (8.902 seconds)
但是,如果我深入挖掘日志和文件系统,我可以找到该查询的结果:
(yarn.resourcemanager.log) org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root OPERATION=AM Released Container TARGET=SchedulerApp RESULT=SUCCESS APPID=application_1572972524483_0022 CONTAINERID=container_1572972524483_0022_01_000002 RESOURCE=<memory:1024, vCores:1> QUEUENAME=default
(container_folder/syslog_attempt) [TezChild] |exec.FileSinkOperator|: New Final Path: FS file:/tmp/<REALLY LONG FILE PATH>/000000_0
[root #] cat /tmp/<REALLY LONG FILE PATH>/000000_0
SEQ"org.apache.hadoop.io.BytesWritableorg.apache.hadoop.io.Textl▒ꩇ1som}▒▒j¹▒ 2060
2060 是分区的正确计数。
现在,奇怪的是,如果我在 HDFS 上插入覆盖目录,我能够从应用程序中获取结果:
hive> set hive.execution.engine=tez;
hive> INSERT OVERWRITE DIRECTORY '/tmp/local_out' select count(*) from external_table where partition_1='1' and partition_2='2';
[root #] hdfs dfs -cat /tmp/local_out/000000_0
2060
但是,尝试插入覆盖本地目录失败:
hive> set hive.execution.engine=tez;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' select count(*) from external_table where partition_1='1' and partition_2='2';
[root #] cat /tmp/local_out/000000_0
cat: /tmp/local_out/000000_0: No such file or directory
如果我为这个查询 cat 容器结果文件,它只是数字,没有 class 名称或特殊字符:
[root #] cat /tmp/<REALLY LONG FILE PATH>/000000_0
2060
我能找到的唯一不合适的日志消息来自 YARN ResourceManager 日志:
(yarn.resourcemanager.log) INFO org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root OPERATION=AM Released Container TARGET=SchedulerApp RESULT=SUCCESS APPID=application_1572972524483_0023 CONTAINERID=container_1572972524483_0023_01_000004 RESOURCE=<memory:1024, vCores:1> QUEUENAME=default
(yarn.resourcemanager.log) WARN org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger: USER=root IP=NMIP OPERATION=AM Released Container TARGET=Scheduler RESULT=FAILURE DESCRIPTION=Trying to release container not owned by app or with invalid id. PERMISSIONS=Unauthorized access or invalid container APPID=application_1572972524483_0023 CONTAINERID=container_1572972524483_0023_01_000004
基于最模糊的印象,我的猜测是当结果写入本地文件系统时存在字符编码问题(因此容器结果文件中的特殊字符)但这实际上只是一个猜测,我不知道如何verify/tackle那个问题。非常感谢任何帮助!
你是如何将数据插入到配置单元中的table? Hive 从 Metastore 而不是 运行 给出 count(*) 结果一个计数作业来优化性能。首先尝试在此 table 上进行 MSCK 修复,让配置单元了解新的外部文件并相应地修改配置单元元存储。
Apache Hive 邮件列表中的某个人建议这是由 YARN 容器将其结果文件写入本地机器 运行 而不是 HDFS 引起的。我在源代码中做了一些挖掘,发现:
mapreduce.framework.name=local
这是 Hadoop 3.2.1 中的默认设置,导致了这个问题。
解决方法:
set mapreduce.framework.name=yarn