Flink/Blink 原理漫谈(二)流表对偶性和distinct详解

系列文章目录

Flink/Blink 原理漫谈(零)运行时的组件

Flink/Blink 原理漫谈(一)时间,watermark详解

Flink/Blink 原理漫谈(二)流表对偶性和distinct详解

Flink/Blink 原理漫谈(三)state 有状态计算机制 详解

Flink/Blink 原理漫谈(四)window机制详解

Flink/Blink 原理漫谈(五)流式计算的持续查询实现 详解

Flink/Blink 原理漫谈(六)容错机制(fault tolerance)详解



流表对偶性

这部分其实很简单……不明白为啥文档写的很复杂。
简单来说,mysql需要进行主备复制,而binlog就是mysql实现主备复制的核心手段。binlog记录了数据库上的所有增、删、更新等操作。binlog中携带时间戳,我们将所有表的操作都按时间进行记录下来形成binlog,而对binlog的event进行回放的过程就是流数据处理的过程,回放的结果恰恰又形成了一张表。也就是表的操作会形成携带时间的事件流,对流的处理又会形成一张不断变化的表,表和流具有等价性,可以互转。这种流与表的信息无损的互转,我们称之为流表对偶性。

DISTINCT

DISTINCT in SELECT Clause

当DISTINCT用在SELECT Clause中表示对查询的columns进行去重。

两种实现

有两种实现方法:

SELECT DISTINCT expressions
 FROM tables

• DISTINCT - 必须放到开始位置
• expressions - 是N(N>=1)个expression,可以是具体的column,也可以是function等任何合法表达式


SELECT expressions 
•	  FROM tablesGROUP BY expressions ;

这两种方法的输出结果一致。

底层原理

对于上面我们说的去重有两种等效的方式,那么在Blink 内部采用了哪种方式实现的呢?我们看一下Blink SQL:
SELECT DISTINCT FirstName, LastName FROM distinct_tab_source
的plan如下:

StreamExecGroupAggregate(groupBy=[FirstName, LastName], select=[FirstName, LastName])
  StreamExecExchange(distribution=[hash[FirstName, LastName]])
    StreamExecCalc(select=[FirstName, LastName])
      StreamExecScan(table=[[distinct_tab_source]])

也就是说在Blink 内部利用GROUP BY Clause实现的去重逻辑

DISTINCT in COUNT AGG、

语法

COUNT(DISTINCT expression)

底层原理

CountDistinct 的核心逻辑是对统计列进行去重计数。
• 数据存储 - 流数据源源不断的到来,要想知道是否有某个值(对应统计列的值)是否流过,那么我们必须记录历史上已经来过的值,以便去重;
• 数据撤回 - 流上数据的更新我们需要Retract机制处理,其中Retract机制里面涉及了消息类型,即 "+/-"来标识消息类型。那么在CountDistinct也要管理“-”的消息,如果已经计数的消息被撤回了,我们需要更新计数统计结果
在这里插入图片描述
• + 记录到来会调用accumulate方法,结合state进行去重计数统计,同时 - 记录到了会调用 retract 方法,结果state 进行撤回记录处理。
• +state和-state的数据结构都是 MapView<colType, LONG>, key是存储col的值,value存储value的记录数
• countState是LONG 类型的基础类型
• -state 实际运行时只有流入的数据正向记录还没有到来时候,才需要进行数据存储(一般很少发生)。
• -state 和 +state (后续版本会合并为一份state,用value的正负判断Event类型)
这无疑会导致state越来越大,更多的性能问题会出现,在未来可能会使用基数估计等方法来解决这样的问题。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章