【问题标题】:Why is this Hive QL expression failing?为什么这个 Hive QL 表达式会失败?
【发布时间】:2016-05-04 18:00:59
【问题描述】:

此查询因神秘的评估错误而失败:

select printf("%08x", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

(这里是例外)

Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: Error evaluating printf('%08x', reflect('java.lang.Integer','reverseBytes',1))

我想要完成的是一致地重现 murmur3 哈希十六进制值的 Java 实现,它使用 hasher getBytes 方法,以大端格式返回它们(并且十进制数字以小端写入) ,因此整数中的字节交换。

单独执行查询的每个部分都可以完美地工作,它将 printf 和反映失败的内容混合在一起......并且只有当格式是数字类型时,才有效:

select printf("%s", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

但这也失败了

select printf("%d", reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

并且我已经确保结果是数字类型而不是字符串,因为我可以对其进行算术运算,例如:

select printf("%s", 10 * reflect('java.lang.Integer', 'reverseBytes', mhash3('123', 0)));

到目前为止,我不需要添加任何自定义 UDF,因此如果有解决方法,我希望保持这种方式。

【问题讨论】:

  • “我可以对其进行算术运算,因为 JVM 在愚蠢的对象包装器上做了一些魔法”“它是一个基础printf 可以直接处理的数字类型”。您是否尝试将 cast() 那个邪恶的 Integer 对象转换为老式 IEEE 整数(又名 int),然后再将其提供给 printf()
  • 准确的说是SQL语法cast( expr as int)
  • 哦,废话,这行得通!如果您写该评论作为答案,我可以接受:)

标签: java hadoop hex string-formatting endianness


【解决方案1】:

Hive 基本上是一个 Java 程序,可以将类似 SQL 的数据类型和表达式转换为 Java 数据类型和 Java/Hadoop 表达式/作业。
在大多数情况下它已经足够复杂了。但是,如果您将自定义 Java 表达式混入其中——这就是 reflect() 的全部意义所在——那么您很可能会陷入边缘情况。

在您的具体问题中,静态 java.lang.Integer.reverseBytes(int) 应该返回原始类型 int 值。但我不确定 Hive 如何在内部处理通用整数值——也许使用long?也许使用自定义对象类型??
无论如何,看起来返回值不能直接作为数字类型输入 Hive printf() 函数。默认情况下,int 可能会转换为String...也许它可以与long 一起使用...

我看到了两种可能的解决方法:

  1. 将对reflect() 的调用包装在子查询中,以便 Hive 隐式转换为 Hive 支持的类型(子查询在编译时合并,不需要额外的 MR 步骤)——存在以下风险Hive 类型仍将是 String
    select printf("%d", WTF) from (select reflect(.....) as WTF from ...) DUH
  2. 需要显式转换为您选择的 Hive 数字类型
    select printf("%d", cast(reflect(.......) as int)) from ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多