flink api和flink sql中得窗口操作及案例

滚动窗口、滑动窗口及会话窗口

/**
     * (1)滚动窗口
     *
     * 滚动窗口(Tumbling windows)要用 Tumble 类来定义, 另外还有三个方法:
     * ⚫ over:定义窗口长度
     * ⚫ on:用来分组(按时间间隔) 或者排序(按行数) 的时间字段
     * ⚫ as:别名,必须出现在后面的 groupBy 中
     */
    // Tumbling Event-time Window (事件时间字段rowtime)
    table1.window(Tumble over 10.minutes on 'rowtime as 'w)
    // Tumbling Processing-time Window (处理时间字段rowtime)
    table1.window(Tumble over 10.minutes on 'proctime as 'w)
    // Tumbling Row-count Window (类似于计数窗口, 按处理时间排序, 10 行一组)
    table1.window(Tumble over 10.rows on 'proctime as 'w)

    /**
     * (2)滑动窗口
     *
     * 滑动窗口(Sliding windows)要用 Slide 类来定义,另外还有四个方法:
     * ⚫ over:定义窗口长度
     * ⚫ every:定义滑动步长
     * ⚫ on:用来分组(按时间间隔)或者排序(按行数)的时间字段
     * ⚫ as:别名,必须出现在后面的 groupBy 中
     */
      // Sliding Event-time Window
    table1.window(Slide over 10.minutes every 5.minutes on 'rowtime as 'w)
      // Sliding Processing-time window
    table1.window(Slide over 10.minutes every 5.minutes on 'proctime as 'w)
      // Sliding Row-count window
    table1.window(Slide over 10.rows every 5.rows on 'proctime as 'w)

    /**
     * (3)会话窗口
     *
     * 会话窗口(Session windows)要用 Session 类来定义, 另外还有三个方法:
     * ⚫ withGap:会话时间间隔
     * ⚫ on:用来分组(按时间间隔)或者排序(按行数)的时间字段
     * ⚫ as:别名,必须出现在后面的 groupBy 中
     */
      // Session Event-time Window
    table1.window(Session withGap 10.minutes on 'rowtime as 'w)
      // Session Processing-time Window
    table1.window(Session withGap 10.minutes on 'proctime as 'w)

无界的 over window及有界的 over window

/**
     * 1) 无界的 over window
     */
      // 无界的事件时间 over window (时间字段 "rowtime")
    table1.window(Over partitionBy 'a orderBy 'rowtime preceding UNBOUNDED_RANGE as 'w)
      //无界的处理时间 over window (时间字段"proctime")
    table1.window(Over partitionBy 'a orderBy 'proctime preceding UNBOUNDED_RANGE as 'w)
      // 无界的事件时间 Row-count over window (时间字段 "rowtime")
    table1.window(Over partitionBy 'a orderBy 'rowtime preceding UNBOUNDED_ROW as 'w)
      //无界的处理时间 Row-count over window (时间字段 "rowtime")
    table1.window(Over partitionBy 'a orderBy 'proctime preceding UNBOUNDED_ROW as 'w)

    /**
     * 2) 有界的 over window
     */
      // 有界的事件时间 over window (时间字段 "rowtime", 之前 1 分钟)
    table1.window(Over partitionBy 'a orderBy 'rowtime preceding 1.minutes as 'w)
      // 有界的处理时间 over window (时间字段 "rowtime", 之前 1 分钟)
    table1.window(Over partitionBy 'a orderBy 'proctime preceding 1.minutes as 'w)
      // 有界的事件时间 Row-count over window (时间字段 "rowtime", 之前 10 行)
    table1.window(Over partitionBy 'a orderBy 'rowtime preceding 10.rows as 'w)
      // 有界的处理时间 Row-count over window (时间字段 "rowtime", 之前 10 行)
    table1.window(Over partitionBy 'a orderBy 'proctime preceding 10.rows as 'w)


    /** 我们已经了解了在 Table API 里 window 的调用方式, 同样,我们也可以在 SQL 中直接加入窗口的定义和使用。 */1)Group Windows

    SQL 支持以下 Group 窗口函数:
        ⚫ TUMBLE(time_attr, interval)
        定义一个滚动窗口,第一个参数是时间字段,第二个参数是窗口长度。
        ⚫ HOP(time_attr, interval, interval)
        定义一个滑动窗口,第一个参数是时间字段,第二个参数是窗口滑动步长,第三个是窗口长度。
        ⚫ SESSION(time_attr, interval)
        定义一个会话窗口,第一个参数是时间字段,第二个参数是窗口间隔(Gap)。

        另外还有一些辅助函数, 可以用来选择 Group Window 的开始和结束时间戳, 以及时间属性。
        这里只写 TUMBLE_*,滑动和会话窗口是类似的(HOP_*, SESSION_*)。
        ⚫ TUMBLE_START(time_attr, interval)
        ⚫ TUMBLE_END(time_attr, interval)
        ⚫ TUMBLE_ROWTIME(time_attr, interval)
        ⚫ TUMBLE_PROCTIME(time_attr, interval)2)Over Windows
      由于 Over 本来就是 SQL 内置支持的语法,所以这在 SQL 中属于基本的聚合操作。所有聚合必须在同一窗口上定义,
      也就是说, 必须是相同的分区、排序和范围。 目前仅支持在当前行范围之前的窗口(无边界和有边界)。注意, ORDER BY 必须在单一的时间属性上指定。

      SELECT
        COUNT(amount) OVER ( PARTITION BY user ORDER BY proctime ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
      FROM
        Orders


      // 也可以做多个聚合
      SELECT
        COUNT(amount) OVER w, SUM(amount) OVER w
      FROM Orders
        WINDOW w AS (PARTITION BY user ORDER BY proctime ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
     

案例

滚动窗口,统计 10 秒内出现的每个 sensor 的个数。

import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.table.api.{EnvironmentSettings, Table, Tumble}
import org.apache.flink.table.api.scala._

/**
 * 可以开一个滚动窗口,统计 10 秒内出现的每个 sensor 的个数。
 */
object _05_FlinkTest {

  def main(args: Array[String]): Unit = {

    // 创建流的执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

    // 读取本地文件
    val dataFrame: DataStream[String] = env.readTextFile("C:\\Users\\user\\Desktop\\数据仓库理论\\flink_sql\\代码\\FlinkTutorial\\src\\main\\resources\\sensor.txt")
    // map成样例类,然后提取水位线
    val ds: DataStream[_02_SensorReading] = dataFrame
      .map(
      data => {
      val arr: Array[String] = data.split(",")
      _02_SensorReading(arr(0), arr(1).toLong, arr(2).toDouble) }
      )
      .assignTimestampsAndWatermarks(
      new BoundedOutOfOrdernessTimestampExtractor[_02_SensorReading](Time.seconds(1)) {
      override def extractTimestamp(t: _02_SensorReading): Long = t.timestamp * 1000L
    })

    // 创建表的执行环境
    val settings: EnvironmentSettings = EnvironmentSettings.newInstance()
      .useBlinkPlanner()
      .inStreamingMode()
      .build()
    val tabEnv: StreamTableEnvironment = StreamTableEnvironment.create(env, settings)
    // 将DataStream转换为Table,并指定时间字段
    val table: Table = tabEnv.fromDataStream(ds,'id,'temperature,'timestamp.rowtime)

    // 滚动窗口,统计 10 秒内出现的每个 sensor 的个数
    /**
     * 第一种:flink table api
     */
    val resTable1: Table = table
      .window(Tumble over 10.seconds on 'timestamp as 'tw)
      .groupBy('id, 'tw)
      .select('id, 'id.count)

    /**
     * 第二种:flink sql
     */
    val sqlTable: Table = table
      .select('id, 'temperature, 'timestamp as 'ts)
    // TUMBLE(time_attr, interval)
    // 定义一个滚动窗口,第一个参数是时间字段,第二个参数是窗口长度。
    val resTable2: Table = tabEnv.sqlQuery(
        "select id,count(id) from " + sqlTable  + " group by id,tumble(ts,interval '10' second) ")

    // resultTable 转换为数据流
    val resDs1: DataStream[(Boolean, (String, Long))] = resTable1.toRetractStream[(String, Long)]
    val resDs2: DataStream[(Boolean, (String, Long))] = resTable2.toRetractStream[(String, Long)]
    resDs1.filter(_._1).print("resDs1 ---> ")
    resDs2.filter(_._1).print("resDs2 ---> ")
    // 执行程序
    env.execute()
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值