Java toChanglelogStream打印不同类型的更改
我在 示例1:Java toChanglelogStream打印不同类型的更改,java,scala,apache-flink,Java,Scala,Apache Flink,我在 示例1: // === EXAMPLE 1 === // interpret the stream as a retract stream // create a changelog DataStream val dataStream = env.fromElements( Row.ofKind(RowKind.INSERT, "Alice", Int.box(12)), Row.ofKind(RowKind.INSERT, "Bob&qu
// === EXAMPLE 1 ===
// interpret the stream as a retract stream
// create a changelog DataStream
val dataStream = env.fromElements(
Row.ofKind(RowKind.INSERT, "Alice", Int.box(12)),
Row.ofKind(RowKind.INSERT, "Bob", Int.box(5)),
Row.ofKind(RowKind.UPDATE_BEFORE, "Alice", Int.box(12)),
Row.ofKind(RowKind.UPDATE_AFTER, "Alice", Int.box(100))
)(Types.ROW(Types.STRING, Types.INT))
// interpret the DataStream as a Table
val table = tableEnv.fromChangelogStream(dataStream)
// register the table under a name and perform an aggregation
tableEnv.createTemporaryView("InputTable", table)
tableEnv
.executeSql("SELECT f0 AS name, SUM(f1) AS score FROM InputTable GROUP BY f0")
.print()
// prints:
// +----+--------------------------------+-------------+
// | op | name | score |
// +----+--------------------------------+-------------+
// | +I | Bob | 5 |
// | +I | Alice | 12 |
// | -D | Alice | 12 |
// | +I | Alice | 100 |
// +----+--------------------------------+-------------+
示例2:
// === EXAMPLE 2 ===
// convert to DataStream in the simplest and most general way possible (no event-time)
val simpleTable = tableEnv
.fromValues(row("Alice", 12), row("Alice", 2), row("Bob", 12))
.as("name", "score")
.groupBy($"name")
.select($"name", $"score".sum())
tableEnv
.toChangelogStream(simpleTable)
.executeAndCollect()
.foreach(println)
// prints:
// +I[Bob, 12]
// +I[Alice, 12]
// -U[Alice, 12]
// +U[Alice, 14]
对于这两个例子,我想问为什么第一个在最后两个记录中打印
-D
和+I
,而第二个打印-U
和+U
。这里有什么规则来决定这种变化?谢谢。产生差异的原因有两部分,它们都在GroupAggFunction
中定义,这是用于处理此查询的处理函数
首先是这部分代码:
//更新聚合结果并设置为新行
if(isAccumulateMsg(输入)){
//积累投入
函数.累加(输入);
}否则{
//收回输入
功能。收回(输入);
}
当接收到给定密钥的新值时,该方法首先检查它是否是累积消息(RowKind.INSERT
或RowKind.UPDATE\u AFTER
)或收回消息(RowKind.UPDATE\u BEFORE
)
在第一个示例中,您自己显式地声明了RowKind
。当执行到达Row.ofKind(RowKind.UPDATE_在“Alice”,Int.box(12)之前)
,这是一条收回消息,它将首先从现有累加器收回输入。这意味着在缩回后,我们会得到一把蓄能器为空的钥匙。发生这种情况时,将达到以下行:
}其他{
//我们收回了这把钥匙的最后一条记录
//发出删除消息
如果(!第一行){
//为前一行准备删除消息
resultRow.replace(currentKey,prevagValue).setRowKind(RowKind.DELETE);
out.collect(resultRow);
}
//并清除所有状态
accState.clear();
//清除当前键下的dataview
function.cleanup();
}
由于这不是键“Alice”接收到的第一行,因此我们为前一行发出一条删除消息,然后下一行将发出一条INSERT
对于第二个示例,您没有明确指定RowKind
,默认情况下,所有消息都是通过RowKind.INSERT
接收的。这意味着现在我们不收回现有累加器,并采用以下代码路径:
如果(!recordCounter.recordCountIsZero(累加器)){
//我们为此密钥聚合了至少一条记录
//更新状态
accState.update(累加器);
//如果这不是第一排,我们必须发出回缩
如果(!第一行){
如果(stateRetentionTime)感谢尤瓦尔·伊扎科夫(yuval Itzhakov)的伟大回答,那真的很有帮助。