执行Apache BEAM sql查询时出错 - 在GroupByKey之前使用Window.into或Window.triggering转换

时间:2018-06-13 22:30:38

标签: apache-beam apache-beam-io

如何在BEAM SQL中包含GroupByKey之前的Window.into或Window.triggering转换?

我有以下2个表:

Ist table

CREATE TABLE table1(
field1 varchar 
,field2 varchar
)

第二桌

CREATE TABLE table2(
field1 varchar
,field3 varchar
)

我正在将结果写在第3张表中

CREATE TABLE table3(
field1 varchar
,field3 varchar
)

前两个表正在从kafka流中读取数据,我正在使用以下查询对这些表进行连接并将数据插入第三个表。前两个表是无界/无界的

INSERT INTO table3 
        (field1, 
         field3) 
SELECT a.field1, 
   b.field3 
FROM   table1 a 
   JOIN table2 b 
     ON a.field1 = b.field1 

我收到以下错误:

  

引起:java.lang.IllegalStateException:GroupByKey不能   适用于没有a的GlobalWindow中的无界PCollection   触发。在之前使用Window.into或Window.triggering变换   GroupByKey。在   org.apache.beam.sdk.transforms.GroupByKey.applicableTo(GroupByKey.java:173)     在   org.apache.beam.sdk.transforms.GroupByKey.expand(GroupByKey.java:204)     在   org.apache.beam.sdk.transforms.GroupByKey.expand(GroupByKey.java:120)     在org.apache.beam.sdk.Pipeline.applyInternal(Pipeline.java:537)at   org.apache.beam.sdk.Pipeline.applyTransform(Pipeline.java:472)at at   org.apache.beam.sdk.values.PCollection.apply(PCollection.java:286)at at   org.apache.beam.sdk.transforms.join.CoGroupByKey.expand(CoGroupByKey.java:126)     在   org.apache.beam.sdk.transforms.join.CoGroupByKey.expand(CoGroupByKey.java:74)     在org.apache.beam.sdk.Pipeline.applyInternal(Pipeline.java:537)at   org.apache.beam.sdk.Pipeline.applyTransform(Pipeline.java:472)at at   org.apache.beam.sdk.transforms.join.KeyedPCollectionTuple.apply(KeyedPCollectionTuple.java:107)     在   org.apache.beam.sdk.extensions.joinlibrary.Join.innerJoin(Join.java:59)     在   org.apache.beam.sdk.extensions.sql.impl.rel.BeamJoinRel.standardJoin(BeamJoinRel.java:217)     在   org.apache.beam.sdk.extensions.sql.impl.rel.BeamJoinRel.buildBeamPipeline(BeamJoinRel.java:161)     在   org.apache.beam.sdk.extensions.sql.impl.rel.BeamProjectRel.buildBeamPipeline(BeamProjectRel.java:68)     在   org.apache.beam.sdk.extensions.sql.impl.rel.BeamAggregationRel.buildBeamPipeline(BeamAggregationRel.java:80)     在   org.apache.beam.sdk.extensions.sql.impl.rel.BeamIOSinkRel.buildBeamPipeline(BeamIOSinkRel.java:64)     在   org.apache.beam.sdk.extensions.sql.impl.planner.BeamQueryPlanner.compileBeamPipeline(BeamQueryPlanner.java:127)     在   com.dss.tss.v2.client.BeamSqlCli.compilePipeline(BeamSqlCli.java:95)     在com.dss.test.v2.client.SQLCli.main(SQLCli.java:100)

1 个答案:

答案 0 :(得分:3)

这是Beam SQL的当前实现限制。您需要define windows然后join the inputs per-window

在Beam SQL中如何进行连接和窗口的几个例子:

  • complex SQL queryHOP窗口和加入;
  • test,它在SQL之外的Java中定义一个窗口,然后使用join;
  • 应用查询
  • 可以找到其他窗口函数的示例here;

<强>背景

问题是由于通常很难为无界数据流定义连接操作这一事实,它不仅限于Beam SQL。

想象一下,例如,当数据处理系统从两个来源接收输入然后必须匹配它们之间的记录时。从高层次的角度来看,这样的系统必须保留它到目前为止看到的所有数据,然后对于每个新记录,它必须遍历第二个输入源中的所有记录,以查看是否存在匹配。当您拥有有限的小数据源时,它可以正常工作。在简单的情况下,您可以将所有内容加载到内存中,匹配来自源的数据,生成输出。

使用流数据,您无法永久缓存它。如果数据永远不会停止怎么办?目前还不清楚你想要发射数据的时间。如果你有一个outer join操作怎么办?你什么时候认为你没有来自另一个输入的匹配记录?

例如,请参阅光束指南的explanation部分中无界PCollections的{​​{3}}。并且Beam中的Joins通常使用GroupByKey(Beam SQL Joins)在其上实现。

对于特定的管道,所有这些问题都可能得到解答,但在一般情况下很难解决这些问题。 Beam SDK和Beam SQL中的当前方法是将其委托给用户以解决具体的业务案例。 Beam允许用户决定将哪些数据汇总到一个CoGroupByKey,等待window多长时间,以及late data结果。还有when to emitstate cells等内容可用于更精细的控制。这允许程序员编写管道来明确定义行为并在某种程度上解决这些问题,并且(很多)额外的复杂性。

Beam SQL是在常规Beam SDK概念之上实现的,并受到相同的限制。但它有更多自己的实现。例如,您没有SQL语法来定义触发器,状态或自定义窗口。或者,您无法编写可以将状态保留在外部服务中的自定义ParDo