流转换成动态表
当流中有新数据到来,初始的表中会插入一行;而基于这个表定义的 SQL 查询,就应该在之前的基础上更新结果。这样得到的表就会不断地动态变化,被称为"动态表"(Dynamic Tables)。动态表是Flink 在Table API 和SQL 中的核心概念,它为流数据处理提供了表和SQL 支持。我们所熟悉的表一般用来做批处理,面向的是固定的数据集,可以认为是"静态表";而动态表则完全不同,它里面的数据会随时间变化。
动态表可以像静态的批处理表一样进行查询操作。由于数据在不断变化,因此基于它定义的 SQL 查询也不可能执行一次就得到最终结果。这样一来,我们对动态表的查询也就永远不会停止,一直在随着新数据的到来而继续执行。这样的查询就被称作"持续查询"(Continuous Query)。对动态表定义的查询操作,都是持续查询;而持续查询的结果也会是一个动态表。由于每次数据到来都会触发查询操作,因此可以认为一次查询面对的数据集,就是当前输入动态表中收到的所有数据。

持续查询的步骤如下:
- 流(stream)被转换为动态表(dynamic table);
- 对动态表进行持续查询(continuous query),生成新的动态表;
- 生成的动态表被转换成流。
动态表是一个快照,每来一条数据进行查询一次,生成一个动态表(快照),连续不断的数据,变成了连续不断的快照,而连续不断的快照连起来这不就是结果流.
将流转换成动态表
为了能够使用 SQL 来做流处理,我们必须先把流(stream)转换成动态表。如果把流看作一张表,那么流中每个数据的到来,都应该看作是对表的一次插入(Insert) 操作,会在表的末尾添加一行数据。因为流是连续不断的,而且之前的输出结果无法改变、只能在后面追加;所以我们其实是通过一个只有插入操作(insert-only)的更新日志(changelog) 流,来构建一个表。
public class TableToDataStreamForLog { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); DataStreamSource<Event> source = env.fromElements( new Event("Alice", "./home", 1000L), new Event("Alice", "./home", 1000L), new Event("Bob", "./cart", 1000L), new Event("Alice", "./prod?id=1", 5 * 1000L), new Event("Cary", "./home", 60 * 1000L), new Event("Bob", "./prod?id=3", 90 * 1000L), new Event("Alice", "./prod?id=7", 105 * 1000L) ); StreamTableEnvironment tableEnvironment = StreamTableEnvironment.create(env); /** * 通过流,stream往上转换到table表结构层 */ Table table = tableEnvironment.fromDataStream(source); /** * 创建视图 */ tableEnvironment.createTemporaryView("eventTable", table); Table result = tableEnvironment.sqlQuery("select user,count(url) from eventTable group by user"); tableEnvironment.toChangelogStream(result).print("sql->"); env.execute("dataToStream"); } }
用户在网站上的点击访问行为,数据类型被包装为 POJO 类型Event。我们将它转换成一个动态表,注册为EventTable。表中的字段定义如下:
[ user: VARCHAR, // 用户名 url: VARCHAR, // 用户访问的 URL ts: BIGINT // 时间戳 ]
当用户点击事件到来时,就对应着动态表中的一次插入(Insert)操作, 每条数据就是表中的一行;随着插入更多的点击事件,得到的动态表将不断增长。

动态表记录了操作类型、数据类型、数据
浙公网安备 33010602011771号