我在Dataflow中有一份工作,通过使用内置的Dataflow API将数据从Bigtable导入Bigquery。我有两个问题:
问题1:如果源数据位于Bigtable中的一个大表中,如何根据给定的Bigtable动态地将其分区为BigQuery中的一组子表或小表行密钥只在运行时知道吗?
Dataflow中的Java代码如下所示:
p.apply(Read.from(CloudBigtableIO.read(config)))
.apply(ParDo.of(new SomeDoFNonBTSourceData()))
.apply(BigQueryIO.Write
.to(PROJ_ID + ":" + BQ_DataSet + "." + BQ_TableName)
.withSchema(schema)
.withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_TRUNCATE)
.withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE_IF_NEEDED));
p.run();
因此,由于BQ_TableName
必须在代码级别提供,我如何根据SomeDoFNonBTSourceData
内部的内容以编程方式提供它,就像当前RowKey的一系列值一样?如果RowKey是'a-c',那么TableA,如果是'd-f',那么TableB等等。
问题2:将Bigtable时间戳导出到Bigquery以便最终在BigQuery中以人类可读的格式重建它的正确方法是什么?
DoFn中的processElement函数如下所示:
public void processElement(ProcessContext c)
{
String valA = new String(c.element().getColumnLatestCell(COL_FAM, COL_NAME).getValueArray());
Long timeStamp = c.element().getColumnLatestCell(COL_FAM, COL_NAME).getTimestamp();
tr.put("ColA", valA);
tr.put("TimeStamp",timeStamp);
c.output(tr);
}
在Pipeline构建期间,timeStamp列的BQ架构设置如下所示:
List<TableFieldSchema> fields = new ArrayList<>();
fields.add(new TableFieldSchema().setName("ColA").setType("STRING"));
fields.add(new TableFieldSchema().setName("TimeStamp").setType("TIMESTAMP"));
schema = new TableSchema().setFields(fields);
因此Bigtable时间戳似乎是Long
类型,我在BQ中尝试了目标TimeStamp列的"TIMESTAMP"
和"INTEGER"
类型(似乎没有Long in BQ就是这样)。最后,我需要将BQ中的TimeStamp列用于“order by”子句,并以人类可读的形式(日期和时间)显示信息。 'order by'部分似乎工作正常,但我没有设法将最终结果CAST转换成任何有意义的东西 - 要么出现强制转换错误,要么仍然无法读取。
答案 0 :(得分:2)
顺便说一下,我在这里寻找类似于问题1 :)的问题的答案。
对于第二个问题,我认为您首先需要确认长时间戳确实是一个UNIX时间戳,我总是假设BQ可以将其作为时间戳摄取而没有任何转换。
但你可以试试这个......
Long longTimeStamp = 1408452095L;
Date timeStamp = new Date();
timeStamp.setTime(longTimeStamp * 1000);
tr.put("TimeStamp", timeStamp.toInstant().toString());