Flink-SQL源码解读(一)window算子的创建的源码分析

本文大体框架参考 https://blog.csdn.net/LS_ice/article/details/90711744

flink版本:1.9

Intro

作为无限流的核心机制,流可以分割为大小有限的窗口,通过在窗口内进行聚合。把源源不断产生的数据根据不同的条件划分成一段一段有边界的数据区间,使用户能够利用窗口功能实现很多复杂的统计分析需求。

windowOperator算子的创建架构

window语法主要是在group by语句中使用,calcite创建WindowOperator算子伴随着聚合策略的实现,包括聚合规则匹配(StreamExecGroupWindowAggregateRule),以及生成聚合physical算子StreamExecGroupWindowAggregate两个子流程

Flink-SQL源码解读(一)window算子的创建的源码分析_第1张图片
Flink-SQL源码解读(一)window算子的创建的源码分析_第2张图片

上图内部流程分析:
应用层SQL:
1.1 window分类及配置,包括滑动、翻转、会话类型窗口
1.2 window时间类型配置,默认待字段名的EventTime,也可以通过PROCTIME()配置为ProcessingTime
Calcite解析引擎:
2.1 Calcite SQL解析,包括逻辑、优化、物理计划和算子绑定(#translateToPlanInternal),在本文特指StreamExecGroupWindowAggregateRule和StreamExecGroupWindowAggregate物理计划
WindowOperator算子创建相关:
3.1 StreamExecGroupWindowAggregate#createWindowOperator创建算子
3.2 WindowAssigner的创建,根据输入的数据,和窗口类型,生成多个窗口
3.3 processElement()真实处理数据,包括聚合运算,生成窗口,更新缓存,提交数据等功能
3.4 Trigger根据数据或时间,来决定窗口触发

StreamExecGroupWindowAggregateRule

/home/graviti/flink/flink-table/flink-table-planner-blink/src/main/scala/org/apache/flink/table/planner/plan/rules/physical/stream/StreamExecGroupWindowAggregateRule.scala

会对window进行提前匹配,生成的WindowEmitStrategy内部具有:是否为EventTime表标识、是否为SessionWindow、early fire和late fire配置、延迟毫秒数(窗口结束时间加上这个毫秒数即数据清理时间)获取聚合逻辑计划中,window配置的时间字段,记录时间字段index信息,window的触发和清理都会用到这个时间

2.1 match匹配是否是group by 语句

  override def matches(call: RelOptRuleCall): Boolean = {
    val agg: FlinkLogicalWindowAggregate = call.rel(0)

    // check if we have grouping sets
    val groupSets = agg.getGroupType != Group.SIMPLE
    if (groupSets || agg.indicator) {
      throw new TableException("GROUPING SETS are currently not supported.")
    }

    true
  }

2.2 生成WindowEmitStrategy 包含window的一些配置属性

/home/graviti/flink/flink-table/flink-table-planner-blink/src/main/scala/org/apache/flink/table/planner/plan/utils/WindowEmitStrategy.scala

object WindowEmitStrategy {
  /**是否为EventTime表标识、
   * 是否为SessionWindow、
   * early fire和late fire配置、
   * 延迟毫秒数(窗口结束时间加上这个毫秒数即数据清理时间)
   * 是否允许延迟
   * @param tableConfig
   * @param window
   * @return
   */
  def apply(tableConfig: TableConfig, window: LogicalWindow): WindowEmitStrategy = {
    val isEventTime = isRowtimeAttribute(window.timeAttribute)
    val isSessionWindow = window.isInstanceOf[SessionGroupWindow]

    val allowLateness = if (isSessionWindow) {
      // ignore allow lateness in session window because retraction is not supported
      0L
    } else if (tableConfig.getMinIdleStateRetentionTime < 0) {
      // min idle state retention time is not set, use 0L as default which means not allow lateness
      0L
    } else {
      // use min idle state retention time as allow lateness
      tableConfig.getMinIdleStateRetentionTime
    }
    val enableEarlyFireDelay = tableConfig.getConfiguration.getBoolean(
      TABLE_EXEC_EMIT_EARLY_FIRE_ENABLED)
    val earlyFireDelay = getMillisecondFromConfigDuration(
      tableConfig, TABLE_EXEC_EMIT_EARLY_FIRE_DELAY)
    val enableLateFireDelay = tableConfig.getConfiguration.getBoolean(
      TABLE_EXEC_EMIT_LATE_FIRE_ENABLED)
    val lateFireDelay = getMillisecondFromConfigDuration(
      tableConfig, TABLE_EXEC_EMIT_LATE_FIRE_DELAY)

    new WindowEmitStrategy(
      isEventTime,
      isSessionWindow,
      earlyFireDelay,
      enableEarlyFireDelay,
      lateFireDelay,
      enableLateFireDelay,
      allowLateness)
  }

下面是convert函数的完整实现

大概分为三个部分:

  • 生成WindowEmitStrategy
  • 生成时间字段index信息

你可能感兴趣的:(Flink源码解读系列,flink,sql)