是否可以根据窗口元素的时间戳动态生成BigQuery表名?

时间:2015-08-24 08:35:46

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

例如,如果我有一个5分钟窗口的数据流流媒体作业从PubSub读取,我明白如果我将一个超过两天的时间戳分配给一个元素,那么将有一个带有此元素的窗口,如果我使用将每日表输出到BigQueryIO.java中描述的BigQuery的示例,该作业将在BigQuery表中使用实际日期写入过去两天的元素。

我想将过去的元素写入BigQuery表,并使用窗口元素的时间戳而不是当前窗口的时间,是否可能?

现在我正在关注DataflowJavaSDK / sdk / src / main / java / com / google / cloud / dataflow / sdk / io / BigQueryIO.java中描述的示例:

    PCollection<TableRow> quotes = ...
    quotes.apply(Window.<TableRow>info(CalendarWindows.days(1)))
       .apply(BigQueryIO.Write
         .named("Write")
         .withSchema(schema)
         .to(new SerializableFunction<BoundedWindow, String>() {
               public String apply(BoundedWindow window) {
                 String dayString = DateTimeFormat.forPattern("yyyy_MM_dd").parseDateTime(
                   ((DaysWindow) window).getStartDate());
                 return "my-project:output.output_table_" + dayString;
               }
             }));

2 个答案:

答案 0 :(得分:5)

如果我理解正确,您希望确保根据元素(引号)的固有时间戳创建BigQuery表,而不是管道运行时的挂钟时间。

TL; DR代码应该已经做了你想做的事情;如果不是,请发布更多详情。

更长的解释: Dataflow中处理的关键创新之一是事件时间处理。这意味着Dataflow中的数据处理几乎完全与处理发生时分离 - 重要的是处理事件的时间。这是在批处理或流数据源上运行完全相同的代码的关键要素(例如,使用处理历史点击日志的相同代码处理实时用户点击事件)。它还可以灵活处理迟到的数据。

请参阅The world beyond batch,“事件时间与处理时间”一节,了解Dataflow处理模型的这一方面的内容(整篇文章非常值得一读)。有关更深入的说明,请参阅VLDB paper。在windowingtriggers的官方文档中,这也以面向用户的方式进行了描述。

因此,不存在“当前窗口”这样的事情,因为管道可以同时处理在不同时间发生并且属于不同窗口的许多不同事件。实际上,正如VLDB论文所指出的,Dataflow管道执行的一个重要部分是“按窗口分组元素”。

在您展示的管道中,我们将使用记录上的provided timestamps将您要写入BigQuery的记录分组到窗口中,并将每个窗口写入其自己的表,如有必要,为新遇到的窗口创建表。如果后期数据到达窗口(请参阅关于窗口的文档和触发器以讨论后期数据),我们将附加到现有表中。

答案 1 :(得分:1)

上述代码不再适用于我。 Google文档中有updated example,但 DaysWindow IntervalWindow 替换为我工作:

 PCollection<TableRow> quotes = ...
 quotes.apply(Window.<TableRow>into(CalendarWindows.days(1)))
   .apply(BigQueryIO.Write
     .named("Write")
     .withSchema(schema)
     .to(new SerializableFunction<BoundedWindow, String>() {
       public String apply(BoundedWindow window) {
         // The cast below is safe because CalendarWindows.days(1) produces IntervalWindows.
         String dayString = DateTimeFormat.forPattern("yyyy_MM_dd")
              .withZone(DateTimeZone.UTC)
              .print(((IntervalWindow) window).start());
         return "my-project:output.output_table_" + dayString;
       }
     }));