Flink SQL 初体验(2)

一、核心概念

1.TableEnvironment 是 Table API 和 SQL 的核心概念。

  • 在内部的 catalog 中注册 Table
  • 注册外部的 catalog
  • 加载可插拔模块
  • 执行 SQL 查询
  • 注册自定义函数 (scalar、table 或 aggregation)
  • DataStream 和 Table 之间的转换(面向 StreamTableEnvironment )

Table 总是与特定的 TableEnvironment 绑定。 不能在同一条查询中使用不同 TableEnvironment 中的表,TableEnvironment 可以通过静态方法 TableEnvironment.create() 创建。

EnvironmentSettings settings = EnvironmentSettings
    .newInstance()
    //这里选择流/批模式
    .inStreamingMode()
    //.inBatchMode()
    .build();

TableEnvironment tEnv = TableEnvironment.create(settings);

或者用户可以从现有的 StreamExecutionEnvironment 创建一个 StreamTableEnvironment 与 DataStream API 互操作。

StreamExecutionEnvironment env = 
    StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tEnv = StreamTableEnvironment.create(env);

二、在Catalog中创建表

TableEnvironment 维护着一个由标识符(identifier)创建的表 catalog 的映射。
标识符由三个部分组成:catalog 名称、数据库名称以及对象名称。如果 catalog 或者数据库没有指明,就会使用当前默认值。

Table 可以是虚拟的(视图 VIEWS)也可以是常规的(表 TABLES)。

  • 视图 VIEWS,可以从已经存在的Table中创建,一般是 Table API 或者 SQL 的查询结果。
  • 表 TABLES,描述的是外部数据,例如文件、数据库表或者消息队列。

2.1 临时表(Temporary Table) 和 永久表(Permanent Table)

表可以是临时的,与单个Flink会话(session)的生命周期相关;也可以是永久的,并且在多个Flink会话和集群中可见。

  • 永久表需要catalog以维护表的元数据。一旦永久表被创建,它将对任何连接到catalog的Flink会话可见且持续存在,直至被明确删除。
  • 临时表通常保存于内存中并且仅在创建它们的Flink会话持续期间存在。这些表对于其他会话是不可见的。它们不与任何catalog或者数据库绑定,但可以在一个命名空间(namespace)中创建。即使它们对应的数据库被删除,临时表也不会被删除。

2.2 表相关API及demo演示

2.2.1创建表

2.2.1.1 虚拟表

在 SQL 的术语中,Table API 的对象对应于视图(虚拟表)。它封装了一个逻辑查询计划。它可以通过以下方法在 catalog 中创建:

// get a TableEnvironment
TableEnvironment tableEnv = ...; 

// table is the result of a simple projection query 
Table projTable = tableEnv.from("X").select(...);

// register the Table projTable as table "projectedTable"
tableEnv.createTemporaryView("projectedTable", projTable);

注意: 从传统数据库系统的角度来看,Table 对象与 VIEW 视图非常像。也就是,定义了 Table 的查询是没有被优化的, 而且会被内嵌到另一个引用了这个注册了的 Table的查询中。如果多个查询都引用了同一个注册了的Table,那么它会被内嵌每个查询中并被执行多次, 也就是说注册了的Table的结果不会被共享。

2.2.1.2 Connector Tables

另外一个方式去创建 TABLE 是通过 connector 声明。Connector 描述了存储表数据的外部系统。存储系统例如 Apache Kafka 或者常规的文件系统都可以通过这种方式来声明。

// Using table descriptors 未实现,此为官方demo 
final TableDescriptor sourceDescriptor = TableDescriptor.forConnector("datagen")
    .schema(Schema.newBuilder()
    .column("f0", DataTypes.STRING())
    .build())
    .option(DataGenOptions.ROWS_PER_SECOND, 100)
    .build();

tableEnv.createTable("SourceTableA", sourceDescriptor);
tableEnv.createTemporaryTable("SourceTableB", sourceDescriptor);
// Using SQL DDL
tEnv.executeSql("CREATE TABLE MySqlPersonAssetTable(" +
    // declare the schema of the table 
    "   trans_date STRING," +
    "   pay_code STRING," +
    "   trans_amt NUMERIC(15,2)," +
    "   trans_summary STRING," +
    "   trans_firm STRING," +
    "   trans_status STRING" +
    ") WITH(" +
    // declare the external system to connect to
    "   'connector'='jdbc'," +
    "   'url' = 'jdbc:mysql://ip:3306/flink?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC'," +
    "   'table-name' = 'person_asset'," +
    "   'username' = 'username'," +
    "   'password' = 'password'" +
    ")");

2.2.2 查询表

2.2.2.1 Table API

Table API 的查询不是由字符串指定,而是在宿主语言中逐步构建。Table API 是基于 Table 类的,该类表示一个表(流或批处理),并提供使用关系操作的方法。这些方法返回一个新的 Table 对象,该对象表示对输入 Table 进行关系操作的结果,一些关系操作由多个方法调用组成。

//简单的Table聚合查询demo
Table mySqlPersonAssetTable = tableEnv.from("MySqlPersonAssetTable");
Table selTable = mySqlPersonAssetTable
		.groupBy($("trans_firm"), $("pay_code"), $("trans_status"))
        .select($("*"));

在这里插入图片描述

Table API 说明了所有流处理和批处理表支持的 Table API 算子。

2.2.2.2 SQL

Flink SQL 是基于实现了SQL标准的 Apache Calcite 的。SQL 查询由常规字符串指定。

//简单的SQL聚合查询demo
Table mySqlPersonAssetTable = tableEnv.from("MySqlPersonAssetTable");
Table sqlQuery = tEnv.sqlQuery(
                " SELECT trans_date, pay_code, trans_summary, trans_status, sum(trans_amt) AS amtSum " +
                " FROM MySqlPersonAssetTable " +
                " GROUP BY trans_firm, pay_code, trans_status ");

在这里插入图片描述

文档 SQL 描述了Flink对流处理和批处理表的SQL支持。

2.2.2.3 Table API 和 SQL混用

Table API 和 SQL 查询的混用非常简单因为它们都返回 Table 对象:

  • 可以在 SQL 查询返回的 Table 对象上定义 Table API 查询。
  • 在 TableEnvironment 中注册的结果表可以在 SQL 查询的 FROM 子句中引用,通过这种方法就可以在 Table API 查询的结果上定义 SQL 查询。

2.2.3 输出表

Table 通过写入 TableSink 输出。TableSink 是一个通用接口,用于支持多种文件格式(如 CSV、Apache Parquet、Apache Avro)、存储系统(如 JDBC、Apache HBase、Apache Cassandra、Elasticsearch)或消息队列系统(如 Apache Kafka、RabbitMQ)。

批处理 Table 只能写入 BatchTableSink,而流处理 Table 需要指定写入 AppendStreamTableSink,RetractStreamTableSink 或者 UpsertStreamTableSink。

tEnv.executeSql("CREATE TABLE EsPersonAssetTable(" +
        // declare the schema of the table 
        "   trans_date STRING," +
        "   pay_code STRING," +
        "   trans_amt NUMERIC(15,2)," +
        "   trans_summary STRING," +
        "   trans_firm STRING," +
        "   trans_status STRING" +
        ") WITH(" +
        // declare the external system to connect to
        "   'connector'='elasticsearch-7', " +
        "   'hosts' = 'http://localhost:9200', " +
        "   'index' = 'asset_detail_20220120', " +
        "   'format' = 'json' " +
        ")");
        
tEnv.executeSql("insert into EsPersonAssetTable select * from MySqlPersonAssetTable");

参考 Table Sources & Sinks 以获取更多关于可用 Sink 的信息以及如何自定义 DynamicTableSink


未完待续...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值