Bigtable-BigQuery通过DataFlow导入:关于表分区和时间戳的2个问题

时间:2017-01-17 13:44:29

标签: google-bigquery google-cloud-dataflow google-cloud-bigtable

我在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转换成任何有意义的东西 - 要么出现强制转换错误,要么仍然无法读取。

1 个答案:

答案 0 :(得分:2)

顺便说一下,我在这里寻找类似于问题1 :)的问题的答案。

对于第二个问题,我认为您首先需要确认长时间戳确实是一个UNIX时间戳,我总是假设BQ可以将其作为时间戳摄取而没有任何转换。

但你可以试试这个......

Long longTimeStamp = 1408452095L;

Date timeStamp = new Date();
timeStamp.setTime(longTimeStamp * 1000);

tr.put("TimeStamp", timeStamp.toInstant().toString());