Gra*_*ley 5 google-cloud-platform google-cloud-dataflow
在我的数据流的管道,我设置字段impressions_raw作为Long一个com.google.api.services.bigquery.model.TableRow对象:
在我的管道中,我读了TableRow回来.但是,而不是一个Long,我回来了Integer.
但是,如果我明确地将值设置为Long大于Integer.MAX_VALUE,例如30亿的值,那么我回来了Long!
似乎Dataflow SDK正在进行某种类型的检查优化.
因此,如果不进行丑陋的类型检查,应该如何以编程方式处理此问题?(也许我错过了一些明显的事)
感谢您的报告。不幸的是,这个问题对于使用TableRow. TableRow我们强烈推荐下面的解决方案 1:在您的管道中尽快转换。
您存储这些值的对象TableRow由 Jackson 在TableRowJsonCoder. 杰克逊的行为正是您所描述的——也就是说,对于这个类:
class MyClass {
Object v;
}
Run Code Online (Sandbox Code Playgroud)
它将使用v = Long.valueOf(<number>)as{v: 30}或序列化一个实例{v: 3000000000}。然而,在反序列化时,它将使用表示答案所需的位数来确定对象的类型。请参阅此帖子。
我想到了两种可能的解决方案,强烈推荐解决方案 1:
不要用作TableRow中间值。也就是说,尽快转换为POJO。发生这种类型混合的关键原因是TableRow本质上是Map<String, Object>杰克逊(或其他编码员)无法知道你想要一个Long背部。有了 POJO,类型就会很清楚。
关闭的另一个好处TableRow是获得高效的编码器,例如AvroCoder。因为TableRows 是与 JSON 进行编码和解码的,所以编码既冗长又缓慢——洗牌TableRow将是 CPU 和 I/O 密集型的。我希望您会看到 Avro 编码的 POJO 比传递TableRow对象的性能要好得多。
有关示例,请参见LaneInfo中TrafficMaxLaneFlow。
编写可以同时处理这两种情况的代码:
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"));
Run Code Online (Sandbox Code Playgroud)
n如果可能的话,您可能需要对第二个变体进行额外的检查null。
| 归档时间: |
|
| 查看次数: |
142 次 |
| 最近记录: |