Flink sql 基本api操作二

一、将表(Table)转换成流(DataStream)

  1. 调用 toDataStream()方法

   将一个Table 对象转换成DataStream 非常简单,只要直接调用表环境的方法 toDataStream() 就可以。

public class TableToDataStream {

    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<Event> source = env.fromElements(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 streamTableEnv = StreamTableEnvironment.create(env);
        /**
         * 通过流,stream往上转换到table表结构层
         */
        Table table = streamTableEnv.fromDataStream(source);
        Table result = streamTableEnv.sqlQuery("select user,timeMillis from " + table);
        streamTableEnv.toDataStream(result).print("sql->");

        env.execute("tableToDataStream");
    }
}

  2. 调用 toChangelogStream()方法

  将 Table类型转换成流打印输出是很简单的;然而,如果我们同样希望将"用户点击次数统计"表 urlCountTable 进行打印输出,就会抛出一个TableException 异常:
Exception in thread “main” org.apache.flink.table.api.TableException: Table sink
‘default_catalog.default_database.Unregistered_DataStream_Sink_1’ doesn’t support consuming update changes …

  这表示当前的TableSink 并不支持表的更新(update)操作。这是什么意思呢?

  因为 print 本身也可以看作一个 Sink 操作,所以这个异常就是说打印输出的 Sink 操作不支持对数据进行更新。具体来说,urlCountTable 这个表中进行了分组聚合统计,所以表中的每一行是会"更新"的。也就是说,Alice 的第一个点击事件到来,表中会有一行(Alice, 1); 第二个点击事件到来,这一行就要更新为(Alice, 2)。但之前的(Alice, 1)已经打印输出了,“覆水难收”,我们怎么能对它进行更改呢?所以就会抛出异常。

  解决的思路是,对于这样有更新操作的表,我们不要试图直接把它转换成DataStream 打印输出,而是记录一下它的"更新日志"(change log)。这样一来,对于表的所有更新操作,就变成了一条更新日志的流,我们就可以转换成流打印输出了。

  代码中需要调用的是表环境的 toChangelogStream()方法:

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");
    }
}

  

posted on 2023-06-04 08:06  溪水静幽  阅读(177)  评论(0)    收藏  举报