Flink流计算中SQL表的概念和原理

前言


Fink在新发布的1.7版本中,不断完善和加强了SQL&Table API方面的功能支持。这使得在流计算过程中,用户同样能够运用熟悉的SQL语句来做数据处理,查询。但是相比于窗体的RDBMS而言,流计算过程中的SQL处理难免让人觉得不是很好理解,毕竟数据不是fixed-sized的,而是连续不断的。所以本文,笔者来聊聊这个略显抽象的概念:流计算过程中的表以及SQL查询的含义。

动态表和动态查询的概念


在流处理过程中,数据是连续的,所以当我们把这些连续接收到的数据记录汇聚到一起然后做呈现的时候,它其实是一种“动态”表。当不断有新的数据来到的时候,这个动态表就不断扩增。所以动态表在这里更恰当的比喻应该是一种状态表信息。当然鉴于这个表的空间有限(状态数据存储受限),后面来的数据要么会覆盖早期相同的数据,要么这个表中过期的数据会被移除。以此维护这个状态表的数据信息。当然,在流式计算中,每一条数据都有一个自带天然属性的信息,就是时间,它可以是process time,又或者说是event time。以下是一张历史访问频率动态表的数据内容信息,它在Flink内部是以State(3个字段域组成)的形式驻留。

SELECT * FROM RatesHistory;

rowtime currency   rate
======= ======== ======
09:00   US Dollar   102
09:00   Euro        114
09:00   Yen           1
10:45   Euro        116
11:15   Euro        119
11:49   Pounds      108

既然表是动态的表,那也就会有动态的查询,这里我们指的一种连续不断的查询(Continuous Queries)。针对同样的查询条件,因为查询表的数据是在不断动态变化的,所以每次连续查询的结果也将会不同。更进一步地来说,连续查询的结果我们又可以作为另外一个动态表。最终构成了下图动态表的处理过程。

在这里插入图片描述

再回到前面的动态表概念,这里的动态表并不会原地更新。它的更新方式是一种append的方式,所以我们会看到Euro的这条记录有2条。然后当我们程序在查询这个表的时候,会认为11:15的那条是准确的记录。但是如果我们带上时间查询条件,把时间限定在10~11点之间,那么Euro的116的那条记录会是我们想要的结果,比如以下查询sql。

SELECT *
FROM RatesHistory AS r
WHERE r.rowtime = (
  SELECT MAX(rowtime)
  FROM RatesHistory AS r2
  WHERE r2.currency = r.currency
  AND r2.rowtime <= TIME '10:58');

会查出这样的结果:

rowtime currency   rate
======= ======== ======
09:00   US Dollar   102
09:00   Yen           1
10:45   Euro        116

同理,我们也可以做这种动态表之间的join操作,这方面详细内容可参阅文末引用链接处。

动态表的时间属性


相比较于传统数据库表的持久性,动态表的数据具有极强的时效性,也不能够恒定持有所有的表状态数据。所以在动态表中,我们要好好利用时间属性在这里的作用。如上节提到的,时间属性是流数据中很关键的信息,我们同样需要利用这个时间属性信息,作为表中的一个关键字段值。比如说,我们完全可以利用动态表做天,小时,甚至分钟级别内的数据存取、查询,然后隔天表状态过期记录由系统自动清除。这样我们完全无需借助外部存储做来表数据的存放。当然,如果空间足够,我们可以存放周期更长的表状态数据,然后做更加完备的查询处理。这里其实是资源消耗和准确率之间的一个trade off了。

引用


[1].https://ci.apache.org/projects/flink/flink-docs-master/dev/table/streaming/dynamic_tables.html
[2].https://ci.apache.org/projects/flink/flink-docs-master/dev/table/streaming/temporal_tables.html

posted @ 2020-01-12 19:08  回眸,境界  阅读(100)  评论(0编辑  收藏  举报