由于 hive 查询错误导致 hadoop 作业出错

Error in hadoop jobs due to hive query error

异常:

2017-06-21 22:47:49,993 FATAL ExecMapper (main): org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing writable org.apache.hadoop.dynamodb.DynamoDBItemWritable@2e17578f
    at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:643)
    at org.apache.hadoop.hive.ql.exec.ExecMapper.map(ExecMapper.java:149)
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50)
    at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:441)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:377)
    at org.apache.hadoop.mapred.Child.run(Child.java:255)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:415)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1132)
    at org.apache.hadoop.mapred.Child.main(Child.java:249)
Caused by: java.lang.RuntimeException: Exception while processing record: org.apache.hadoop.dynamodb.DynamoDBItemWritable@2e17578f
    at org.apache.hadoop.hive.dynamodb.DynamoDBObjectInspector.getColumnData(DynamoDBObjectInspector.java:136)
    at org.apache.hadoop.hive.dynamodb.DynamoDBObjectInspector.getStructFieldData(DynamoDBObjectInspector.java:97)
    at org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters$StructConverter.convert(ObjectInspectorConverters.java:328)
    at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:626)
    ... 9 more
Caused by: java.lang.NumberFormatException: For input string: "17664956244983174066"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:444)
    at java.lang.Long.parseLong(Long.java:483)
    at org.apache.hadoop.hive.dynamodb.DynamoDBDataParser.getNumberObject(DynamoDBDataParser.java:179)
    at org.apache.hadoop.hive.dynamodb.type.HiveDynamoDBNumberType.getHiveData(HiveDynamoDBNumberType.java:28)
    at org.apache.hadoop.hive.dynamodb.DynamoDBObjectInspector.getColumnData(DynamoDBObjectInspector.java:128)
    ... 12 more

我发送的配置单元查询是:

INSERT OVERWRITE TABLE temp_1 
         SELECT * FROM temp_2 
         WHERE t_id="17664956244983174066" and t_ts="636214684577250000000";

这个数字是不是太大了,不能转换成int?我什至尝试发送不带引号的 17664956244983174066,但我得到了同样的异常。

t_idhive tableN 中定义为 BIGINT 或 dynamobd

中的数字

编辑:

我尝试将 t_id 定义为 string ==> Schema mismatch as dynamodb stores this as int

t_id 作为 double ==>> precision lost. no match.

这里有什么解决办法?

Is this number too big to be converted to int?

是的,这个数字太大了,无法转换为整型。根据 Numeric Types 上的 Apache Hive 文档,BIGINT 的最大值为 9223372036854775807。您的输入 17664956244983174066 大于该值。

以下是普通的 Hive 查询(未集成 DynamoDB),展示了尝试将各种输入转换为 BIGINT 的效果。

SELECT
    "9223372036854775807" AS str,
    cast("9223372036854775807" AS BIGINT) AS numbigint,
    cast("9223372036854775807" AS DOUBLE) AS numdouble
UNION ALL
SELECT
    "9223372036854775808" AS str,
    cast("9223372036854775808" AS BIGINT) AS numbigint,
    cast("9223372036854775808" AS DOUBLE) AS numdouble
UNION ALL
SELECT
    "17664956244983174066" AS str,
    cast("17664956244983174066" AS BIGINT) AS numbigint,
    cast("17664956244983174066" AS DOUBLE) AS numdouble
;

    str numbigint   numdouble
0   9223372036854775807 9223372036854775807 9.2233720368547758e+18
1   9223372036854775808 NULL    9.2233720368547758e+18
2   17664956244983174066    NULL    1.7664956244983173e+19

在记录的最大值 BIGINT 处,该值正确转换。仅高 1 时,转换失败,导致 NULL。您的输入也会发生同样的事情。

该查询还表明转换为 DOUBLE 成功。也许这是一个解决方案,具体取决于您的用例。与整数数据类型相比,这会带来遇到浮点精度问题的风险。

从您的堆栈跟踪来看,对于这种情况,DynamoDB 集成似乎导致 NumberFormatException 而不是 NULL。这可以说是 DynamoDB 连接器中的一个错误,但即使将其更改为映射到 NULL,您仍然无法成功转换。

您的数字超出了 bigint 的范围。
将两边的所有内容都定义为字符串。

根据 https://www.tutorialspoint.com/hive/hive_data_types.htm ,DECIMAL 类型适合您。

The DECIMAL type in Hive is as same as Big Decimal format of Java. It is used for representing immutable arbitrary precision. The syntax and example is as follows:

DECIMAL(precision, scale)
decimal(10,0)

我没有使用过电子病历,但这是我的猜测:)

Hive 会自动尝试转换您的输入,因为您的目标字段是 BigInt,您尝试过这样的操作吗?

INSERT OVERWRITE TABLE temp_1 
SELECT * FROM temp_2 
WHERE cast(t_id as string)="17664956244983174066" and cast(t_ts as string)="636214684577250000000";

根据我的经验,这应该可以避免转换您的输入,但是您可能会在新的 table 中插入异常,您可以在 select 期间转换您的字段,如果您也有许多专栏你也可以试试这个

https://community.hortonworks.com/questions/7703/whether-hive-supports-hive-select-all-query-with-e.html

AWS专家的解决方案是

  1. git 克隆开源 emr-dynamodb-connector
  2. 修改代码
  3. 准备你自己的罐子
  4. 使用引导程序将其上传到 EMR
  5. 在 run_job_flow 中,发送 hadoop env 的配置,并在 HADOOP_CLASSPATH.
  6. 中附加您自己的 jar 位置

我不太喜欢 Java,修改 emr-dynamodb-connector 对我来说是不可能的,但这是解决方案。还可以做两件事...如果你不在 Dynamodb 中使用 Strings,将 hivestring 映射到 Dynamodb 的 number,否则添加映射和支持decimal 从 hive 到 Dynamodb number