Flink-Table Streaming 时态表(Temporal Tables)(七)

时态表表示一个可变表上(参数化)视图的概念,该视图返回表在特定时间点的内容。
变更表可以是跟踪变更的变更历史表(如数据库变更日志),也可以是具体化变更的变更维度表(如数据库表)。
对于更改历史表,Flink可以跟踪更改,并允许在查询中的某个时间点访问表的内容。在Flink中,这种表由一个时态表函数表示。
对于更改维度表,Flink允许在查询中的处理时间访问表的内容。在Flink中,这种表由一个时态表表示。

一、Motivation(动机)

  • 1、与不断变化的历史表相关联(Correlate with a changing history table)
    假设我们有下表RatesHistory.
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

汇率表是一个不断增长的日元汇率附加表(汇率为1)。例如,欧元对日元的汇率从09:00到10:45为114。从10:45到11:15是116。

考虑到我们希望在10:58时输出所有当前速率,我们需要以下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');

相关子查询确定对应的货币的最大时间低于或等于期望的时间。外部查询列出具有最大时间戳的速率。

下表显示了这种计算的结果。在我们的例子中,10:45时欧元的更新被考虑在内,但是11:15时欧元的更新和10:58时表格版本中不考虑英镑的新条目。

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

时态表的概念旨在简化此类查询,加快它们的执行速度,并减少Flink的状态使用。临时表是仅追加表上的参数化视图,它将仅追加表的行解释为表的变更日志,并在特定时间点提供该表的版本。将append only表解释为变更日志需要指定主键属性和时间戳属性。主键确定覆盖哪些行,时间戳确定行有效的时间。
在上面的示例中,currency将是RatesHistory表的主键,rowtime将是timestamp属性。
在Flink中,这由一个时态表函数表示。

  • 2、与更改维度表关联(Correlate with a changing dimension table)
    另一方面,一些用例需要连接一个不断变化的维度表,这个维度表是一个外部数据库表。
    假设latest rate s是一个表(例如,存储在中),它以最新的速率具体化。后来者是物化的历史资本家。那么10:58的LatestRates表的内容将是:
10:58> SELECT * FROM LatestRates;
currency   rate
======== ======
US Dollar   102
Yen           1
Euro        116

    12:00时LatestRates表的内容为:

12:00> SELECT * FROM LatestRates;
currency   rate
======== ======
US Dollar   102
Yen           1
Euro        119
Pounds      108

    在Flink中,这由一个时态表表示。

二、时态表函数(Temporal Table Function)
为了访问临时表中的数据,必须传递一个时间属性,该属性确定将返回的表的版本。Flink使用表函数的SQL语法来提供一种表达它的方法。

定义后,临时表函数接受单个时间参数timeAttribute并返回一组行。此集合包含相对于给定时间属性的所有现有主键的行的最新版本。

假设我们基于RatesHistory表定义了一个时态表函数Rates(timeAttribute),我们可以通过以下方式查询这样一个函数:

SELECT * FROM Rates('10:15');

rowtime currency   rate
======= ======== ======
09:00   US Dollar   102
09:00   Euro        114
09:00   Yen           1

SELECT * FROM Rates('11:00');

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

每个对Rates(timeAttribute)的查询都将返回给定timeAttribute的Rates状态。

注意:目前,Flink不支持使用常量time属性参数直接查询时态表函数。目前,时态表函数只能在连接中使用。上面的示例用于提供有关函数速率(timeAttribute)返回值的直观信息。

有关如何与时态表联接的详细信息,请参见关于连续查询联接的页面

  • 定义时太表函数(Defining Temporal Table Function)
    下面的代码片段演示如何从只追加的表创建临时表函数。
import org.apache.flink.table.functions.TemporalTableFunction;
(...)

// Get the stream and table environments.
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tEnv = StreamTableEnvironment.create(env);

// Provide a static data set of the rates history table.
List<Tuple2<String, Long>> ratesHistoryData = new ArrayList<>();
ratesHistoryData.add(Tuple2.of("US Dollar", 102L));
ratesHistoryData.add(Tuple2.of("Euro", 114L));
ratesHistoryData.add(Tuple2.of("Yen", 1L));
ratesHistoryData.add(Tuple2.of("Euro", 116L));
ratesHistoryData.add(Tuple2.of("Euro", 119L));

// Create and register an example table using above data set.
// In the real setup, you should replace this with your own table.
DataStream<Tuple2<String, Long>> ratesHistoryStream = env.fromCollection(ratesHistoryData);
Table ratesHistory = tEnv.fromDataStream(ratesHistoryStream, "r_currency, r_rate, r_proctime.proctime");

tEnv.registerTable("RatesHistory", ratesHistory);

// Create and register a temporal table function.
// Define "r_proctime" as the time attribute and "r_currency" as the primary key.
TemporalTableFunction rates = ratesHistory.createTemporalTableFunction("r_proctime", "r_currency"); // <==== (1)
tEnv.registerFunction("Rates", rates);                         

    第(1)行创建一个rates临时表函数,它允许我们使用table API中的函数rates。
    第(2)行在我们的表环境中的名称Rates下注册了这个函数,这允许我们在SQL中使用Rates函数。
三、时间表(Temporal Table)

注意:这只在Blink planner中支持。

为了访问临时表中的数据,当前必须使用LookupableTableSource定义一个表源。Flink使用FOR SYSTEM TIME-AS-of的SQL语法来查询时态表,这是SQL:2011中提出的。
假设我们定义了一个名为LatestRates的时态表,我们可以通过以下方式查询这样一个表:

SELECT * FROM LatestRates FOR SYSTEM_TIME AS OF TIME '10:15';

currency   rate
======== ======
US Dollar   102
Euro        114
Yen           1

SELECT * FROM LatestRates FOR SYSTEM_TIME AS OF TIME '11:00';

currency   rate
======== ======
US Dollar   102
Euro        116
Yen           1

注意:目前,Flink不支持在时间不变的情况下直接查询时态表。目前,时态表只能用于连接。上面的示例用于提供有关时态表延迟返回的内容的直觉。

有关如何与时态表联接的详细信息,请参见关于连续查询联接的页面

  • 定义时态表(Defining Temporal Table)
// Get the stream and table environments.
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tEnv = TableEnvironment.getTableEnvironment(env);

// Create an HBaseTableSource as a temporal table which implements LookableTableSource
// In the real setup, you should replace this with your own table.
HBaseTableSource rates = new HBaseTableSource(conf, "Rates");
rates.setRowKey("currency", String.class);   // currency as the primary key
rates.addColumn("fam1", "rate", Double.class);

// register the temporal table into environment, then we can query it in sql
tEnv.registerTableSource("Rates", rates);

官网地址:Temporal Tables

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

springk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值