【问题标题】:Dataflow mixing Integer & Long types数据流混合整数和长类型
【发布时间】:2015-11-10 03:14:15
【问题描述】:

在我的 Dataflow 管道中,我在 com.google.api.services.bigquery.model.TableRow 对象中将字段 impressions_raw 设置为 Long

在我的管道中,我读回了TableRow。但我得到的不是Long,而是Integer

但是,如果我将值明确设置为大于Integer.MAX_VALUELong 值,例如30 亿,那么我会返回Long

Dataflow SDK 似乎在后台进行了某种类型检查优化。

那么,如果不进行丑陋的类型检查,应该如何以编程方式处理呢? (也许我错过了一些明显的东西)

【问题讨论】:

  • 您能发布一些创建、修改和读取这些对象的代码吗?
  • 尼克,我在gist.github.com/dhalperi/…发布了一个语法很好的示例

标签: google-cloud-platform google-cloud-dataflow


【解决方案1】:

感谢您的报告。不幸的是,这个问题是使用TableRow 的根本问题。我们强烈推荐以下解决方案 1:在您的管道中尽快转换为远离 TableRow

您存储这些值的TableRow 对象在TableRowJsonCoder 内部由Jackson 序列化和反序列化。 Jackson 具有您所描述的行为——也就是说,对于这个类:

class MyClass {
    Object v;
}

它将带有v = Long.valueOf(<number>) 的实例序列化为{v: 30}{v: 3000000000}。然而,在反序列化时,它将使用表示答案所需的位数来确定对象的类型。见this SO post

想到了两种可能的解决方案,强烈推荐解决方案 1:

  1. 不要使用TableRow 作为中间值。也就是说,尽快转换成POJO。发生这种类型混合的关键原因是TableRow 本质上是Map<String, Object>,而Jackson(或其他编码人员)无法知道你想要Long 回来。使用 POJO,类型会很清晰。

    关闭TableRow 的另一个好处是获得高效的编码器,例如AvroCoder。因为TableRows 是从JSON 编码和解码的,所以编码既冗长又缓慢——改组TableRow 将是CPU 和I/O 密集型的。我希望您会看到使用 Avro 编码的 POJO 的性能比传递 TableRow 对象时要好得多。

    例如,请参阅LaneInfo in TrafficMaxLaneFlow

  2. 编写可以同时处理这两种情况的代码:

    long numberToLong(@Nonnull Number n) {
        return n.longValue();
    }
    long x = numberToLong((Number) row.get("field"));
    
    Long numberToLong(@Nonnull Number n) {
        if (n instanceof Long) {
            // avoid a copy
            return n;
        }
        return Long.valueOf(n.longValue());
    }
    Long x = numberToLong((Number) row.get("field"));
    

    如果n 可能是null,您可能需要对第二个变体进行额外检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 2014-04-28
    相关资源
    最近更新 更多