Flink-10 Table API 与SQL

1 需要引入的pom依赖

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-planner_2.12</artifactId>
    <version>1.10.1</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-api-scala-bridge_2.12</artifactId>
    <version>1.10.1</version>
</dependency>

2 简单了解TableAPI

def main(args: Array[String]): Unit = {
  val env = StreamExecutionEnvironment.getExecutionEnvironment
  env.setParallelism(1)

  val inputStream = env.readTextFile("..\\sensor.txt")
  val dataStream = inputStream
    .map( data => {
      val dataArray = data.split(",")
      SensorReading(dataArray(0).trim, dataArray(1).trim.toLong, dataArray(2).trim.toDouble)
    }
    )
  // 基于env创建 tableEnv
val settings: EnvironmentSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env, settings)

  // 从一条流创建一张表
  val dataTable: Table = tableEnv.fromDataStream(dataStream)

  // 从表里选取特定的数据
  val selectedTable: Table = dataTable.select('id, 'temperature)
    .filter("id = 'sensor_1'")

  val selectedStream: DataStream[(String, Double)] = selectedTable
    .toAppendStream[(String, Double)]

  selectedStream.print()

  env.execute("table test")

}

1 动态表

如果流中的数据类型是case class可以直接根据case class的结构生成table

tableEnv.fromDataStream(dataStream) 

或者根据字段顺序单独命名

tableEnv.fromDataStream(dataStream,’id,’timestamp  .......)  

或者根据字段顺序单独命名

tableEnv.fromDataStream(dataStream,’id,’timestamp  .......)

最后的动态表可以转换为流进行输出

table.toAppendStream[(String,String)]

2 字段

用一个单引放到字段前面来标识字段名, 如 ‘name , ‘id ,’amount 等

3 TableAPI 的窗口聚合操作

1 通过一个例子了解TableAPI

// 统计每10秒中每个传感器温度值的个数
def main(args: Array[String]): Unit = {
  val env = StreamExecutionEnvironment.getExecutionEnvironment
  env.setParallelism(1)
  env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

  val inputStream = env.readTextFile("..\\sensor.txt")
  val dataStream = inputStream
    .map( data => {
      val dataArray = data.split(",")
      SensorReading(dataArray(0).trim, dataArray(1).trim.toLong, dataArray(2).trim.toDouble)
    }
    )
    .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(1)) {
      override def extractTimestamp(element: SensorReading): Long = element.timestamp * 1000L
    })
  // 基于env创建 tableEnv
val settings: EnvironmentSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env, settings)

  // 从一条流创建一张表,按照字段去定义,并指定事件时间的时间字段
  val dataTable: Table = tableEnv.fromDataStream(dataStream, 'id, 'temperature, 'ts.rowtime)

  // 按照时间开窗聚合统计
  val resultTable: Table = dataTable
    .window( Tumble over 10.seconds on 'ts as 'tw )
    .groupBy('id, 'tw)
    .select('id, 'id.count)

  val selectedStream: DataStream[(Boolean, (String, Long))] = resultTable
    .toRetractStream[(String, Long)]

  selectedStream.print()

  env.execute("table window test")
}

2 关于group by

  1. 如果了使用 groupby,table转换为流的时候只能用toRetractDstream
val dataStream: DataStream[(Boolean, (String, Long))] = table
.toRetractStream[(String,Long)]

  1. toRetractDstream 得到的第一个boolean型字段标识 true就是最新的数据(Insert),false表示过期老数据(Delete)
val dataStream: DataStream[(Boolean, (String, Long))] = table
.toRetractStream[(String,Long)]
dataStream.filter(_._1).print()

  1. 如果使用的api包括时间窗口,那么窗口的字段必须出现在groupBy中。
val resultTable: Table = dataTable
    .window( Tumble over 10.seconds on 'ts as 'tw )
    .groupBy('id, 'tw)
    .select('id, 'id.count)


3 关于时间窗口

  1. 用到时间窗口,必须提前声明时间字段,如果是processTime直接在创建动态表时进行追加就可以。
val dataTable: Table = tableEnv.fromDataStream(dataStream, 'id, 'temperature, 'ps.proctime)

  1. 如果是EventTime要在创建动态表时声明
val dataTable: Table = tableEnv.fromDataStream(dataStream, 'id, 'temperature, 'ts.rowtime)
  1. 滚动窗口可以使用Tumble over 10000.millis on 来表示
val resultTable: Table = dataTable
    .window( Tumble over 10.seconds on 'ts as 'tw )
    .groupBy('id, 'tw)
    .select('id, 'id.count)

4 SQL如何编写

// 统计每10秒中每个传感器温度值的个数
def main(args: Array[String]): Unit = {
  val env = StreamExecutionEnvironment.getExecutionEnvironment
  env.setParallelism(1)
  env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

  val inputStream = env.readTextFile("..\\sensor.txt")
  val dataStream = inputStream
    .map( data => {
      val dataArray = data.split(",")
      SensorReading(dataArray(0).trim, dataArray(1).trim.toLong, dataArray(2).trim.toDouble)
    }
    )
    .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(1)) {
      override def extractTimestamp(element: SensorReading): Long = element.timestamp * 1000L
    })
  // 基于env创建 tableEnv
val settings: EnvironmentSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env, settings)

  // 从一条流创建一张表,按照字段去定义,并指定事件时间的时间字段
  val dataTable: Table = tableEnv.fromDataStream(dataStream, 'id, 'temperature, 'ts.rowtime)

  // 直接写sql完成开窗统计 
  val resultSqlTable: Table = tableEnv.sqlQuery("select id, count(id) from "
  + dataTable + " group by id, tumble(ts, interval '15' second)")

  val selectedStream: DataStream[(Boolean, (String, Long))] = resultSqlTable.toRetractStream[(String, Long)]

  selectedStream.print()

  env.execute("table window test")
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值