【Flink SQL】Flink SQL 基础概念:SQL 动态表 连续查询

news2024/11/18 15:33:09

Flink SQL 基础概念:SQL 动态表 & 连续查询

  • 1.SQL 应用于流处理的思路
  • 2.流批处理的异同点及将 SQL 应用于流处理核心解决的问题
  • 3.SQL 流处理的输入:输入流映射为 SQL 动态输入表
  • 4.SQL 流处理的计算:实时处理底层技术 - SQL 连续查询
  • 5.SQL 流处理实际应用:动态表 & 连续查询技术的两个实战案例
    • 5.1 查询案例一
    • 5.2 案例二
  • 6.SQL 连续查询的两种类型:更新(Update)查询 & 追加(Append)查询
  • 7.SQL 流处理的输出:动态输出表转化为输出数据
  • 8.补充知识:SQL 与关系代数

1.SQL 应用于流处理的思路

在流式 SQL 诞生之前,所有的基于 SQL 的数据查询都是基于批数据的,没有将 SQL 应用到流数据处理这一说法。

那么如果我们想将 SQL 应用到流处理中,必然要站在巨人的肩膀(批数据处理的流程)上面进行,那么具体的分析思路如下:

  • 1️⃣ 先比较 批处理流处理 的异同之处:如果有相同的部分,那么可以直接复用;不同之处才是我们需要重点克服和关注的。
  • 2️⃣ 摘出 1️⃣ 中说到的不同之处,分析如果要满足这个不同之处,目前有哪些技术是类似的。
  • 3️⃣ 再从这些类似的技术上进一步发展,以满足将 SQL 应用于流任务中。

博主下文就会根据上述三个步骤来一步一步介绍 动态表 诞生的背景以及这个概念是如何诞生的。

2.流批处理的异同点及将 SQL 应用于流处理核心解决的问题

首先对比一下常见的 批处理流处理数据源(输入表)处理逻辑数据汇(结果表)的异同点。

输入表
处理逻辑
结果表
批处理静态表:输入数据有限、是有界集合批式计算:每次执行查询能够访问到完整的输入数据,然后计算,输出完整的结果数据静态表:数据有限
流处理动态表:输入数据无限,数据实时增加,并且源源不断流式计算:执行时不能够访问到完整的输入数据,每次计算的结果都是一个中间结果动态表:数据无限

对比上述流批处理之后,我们得到了要将 SQL 应用于流式任务的三个要解决的核心点:

  • 1️⃣ SQL 输入表:分析如何将一个实时的,源源不断的输入流数据表示为 SQL 中的输入表。
  • 2️⃣ SQL 处理计算:分析将 SQL 查询逻辑翻译成什么样的底层处理技术才能够实时的处理流式输入数据,然后产出流式输出数据。
  • 3️⃣ SQL 输出表:分析如何将 SQL 查询输出的源源不断的流数据表示为一个 SQL 中的输出表。

将上面 3 个点总结一下,也就引出了本节的 动态表连续查询 两种技术方案:

  • 动态表:源源不断的输入、输出流数据映射到动态表。
  • 连续查询:实时处理输入数据,产出输出数据的实时处理技术。

3.SQL 流处理的输入:输入流映射为 SQL 动态输入表

动态表。这里的动态其实是相比于批处理的静态(有界)来说的。

  • 静态表:应用于批处理数据中,静态表可以理解为是不随着时间实时进行变化的。一般都是一天、一小时的粒度新生成一个分区。
  • 动态表:动态表是随时间实时进行变化的。是将 SQL 体系中表的概念应用到 Flink 上面的的核心点。

来看一个具体的案例,下图显示了点击事件流(左侧)如何转换为动态表(右侧)。当数据源生成更多的点击事件记录时,映射出来的动态表也会不断增长,这就是动态表的概念:
在这里插入图片描述

4.SQL 流处理的计算:实时处理底层技术 - SQL 连续查询

部分高级关系数据库系统提供了一个称为 物化视图Materialized Views)的特性。

物化视图其实就是一条 SQL 查询,就像常规的虚拟视图 VIEW 一样。但与虚拟视图不同的是,物化视图会缓存查询的结果,因此在请求访问视图时不需要对查询进行重新计算,可以直接获取物化视图的结果,小伙伴萌可以认为物化视图其实就是把结果缓存了下来。

举个例子:批处理中,如果以 Hive 天级别的物化视图来说,其实就是每天等数据源准备好之后,调度物化视图的 SQL 执行然后产生新的结果提供服务。那么就可以认为一条表示了输入、处理、输出的 SQL 就是一个构建物化视图的过程。

映射到我们的流任务中,输入、处理逻辑、输出这一套流程也是一个物化视图的概念。相比批处理来说,流处理中,我们的数据源表的数据是源源不断的。那么从输入、处理、输出的整个物化视图的维护流程也必须是实时的。

因此我们就需要引入一种 实时视图维护Eager View Maintenance)的技术去做到:一旦更新了物化视图的数据源表就立即更新视图的结果,从而保证输出的结果也是最新的。

这种实时视图维护的技术就叫做 连续查询Continuous Query)。

注意:

  • 连续查询 不断的消费动态输入表的的数据,不断的更新动态结果表的数据。
  • 连续查询 的产出的结果 = = = 批处理模式在输入表的上执行的相同查询的结果。相同的 SQL,对应于同一个输入数据,虽然执行方式不同,但是流处理和批处理的结果是永远都会相同的。

5.SQL 流处理实际应用:动态表 & 连续查询技术的两个实战案例

动态表 & 连续查询 两项技术在一条流 SQL 中的执行流程总共包含了三个步骤,如下图及总结所示:

在这里插入图片描述

  • 1️⃣ 将数据输入流转换为 SQL 中的动态输入表。这里的转化其实就是指将输入流映射(绑定)为一个动态输入表。上图虽然分开画了,但是可以理解为一个东西。
  • 2️⃣ 在动态输入表上执行一个连续查询,然后生成一个新的动态结果表。
  • 3️⃣ 生成的动态结果表被转换回数据输出流。

我们实际介绍一个案例来看看其运行方式,以上文介绍到的点击事件流为例,点击事件流数据的字段如下:

[
  user:  VARCHAR,   // 用户名
  cTime: TIMESTAMP, // 访问 URL 的时间
  url:   VARCHAR    // 用户访问的 URL
]

第一步,将输入数据流映射为一个动态输入表。以下图为例,我们将点击事件流(图左)转换为动态表 (图右)。当点击数据源源不断的来到时,动态表的数据也会不断的增加。
在这里插入图片描述
第二步,在点击事件流映射的动态输入表上执行一个连续查询,并生成一个新的动态输出表。

下面介绍两个查询的案例。

5.1 查询案例一

第一个查询:一个简单的 GROUP BY COUNT 聚合查询,写过 SQL 的都不会陌生吧,这种应该都是最基础,最常用的对数据按照类别分组的方法。

如下图所示 group by 聚合的常用案例。
在这里插入图片描述
那么本案例中呢,是基于 clicks 表中 user 字段对 clicks 表(点击事件流)进行分组,来统计每一个 user 的访问的 URL 的数量。下面的图展示了当 clicks 输入表来了新数据(即表更新时),连续查询 的计算逻辑。
在这里插入图片描述
当查询开始,clicks 表(左侧)是空的。

  • 当第一行数据被插入到 clicks 表时,连续查询开始计算结果数据。数据源表第一行数据 [Mary,./home] 输入后,会计算结果 [Mary, 1] 插入结果表。
  • 当第二行 [Bob, ./cart] 插入到 clicks 表时,连续查询会计算结果 [Bob, 1],并插入到结果表。
  • 第三行 [Mary, ./prod?id=1] 输出时,会计算出 [Mary, 2]userMary 的数据总共来过两条,所以为 2),并更新结果表,[Mary, 1] 更新成 [Mary, 2]
  • 最后,当第四行数据加入 clicks 表时,查询将第三行 [Liz, 1] 插入结果表中。

注意上述特殊标记出来的字体,可以看到连续查询对于结果的数据输出方式有两种:

  • 插入insert)结果表
  • 更新update)结果表

大家对于 插入insert)结果表这件事都比较好理解,因为离线数据都只有插入这个概念。但是 更新update)结果表就是离线处理中没有概念了。这就是连续查询中中比较重要一个概念。后文会介绍。

5.2 案例二

接下来介绍第二条查询语句。第二条查询与第一条类似,但是 group by 中除了 user 字段之外,还 group bytumble,其代表开了个滚动窗口(后面会详细说明滚动窗口的作用),然后计算 url 数量。

group by user,是按照类别(横向)给数据分组,group by tumble 滚动窗口是按时间粒度(纵向)给数据进行分组。如下图所示。

在这里插入图片描述
图形化一解释就很好理解了,两种都是对数据进行分组,一个是按照 类别 分组,另一种是按照 时间 分组。

与前面一样,左边显示了输入表 clicks。查询每小时持续计算结果并更新结果表。clicks 表有三列,usercTimeurl。其中 cTime 代表数据的时间戳,用于给数据按照时间粒度分组。

在这里插入图片描述
我们的滚动窗口的步长为 1 小时,即时间粒度上面的分组为 1 小时。其中时间戳在 12:00:00 - 12:59:59 之间有四条数据。13:00:00 - 13:59:59 有三条数据。14:00:00 - 14:59:59 之间有四条数据。

  • 12:00:00 - 12:59:59 数据输入之后,1 小时的窗口,连续查询计算的结果如上图所示,将 [Mary, 3][Bob, 1] 插入结果表。
  • 13:00:00 - 13:59:59 数据输入之后,1 小时的窗口,连续查询计算的结果如上图所示,将 [Bob, 1][Liz, 2] 插入结果表。
  • 14:00:00 - 14:59:59 数据输入之后,1 小时的窗口,连续查询计算的结果如上图所示,将 [Mary, 1][Bob, 2][Liz, 1] 插入结果表。

而这个查询只有 插入insert)结果表这个行为。

6.SQL 连续查询的两种类型:更新(Update)查询 & 追加(Append)查询

虽然前一节的两个查询看起来非常相似(都计算分组进行计数聚合),但它们在一个重要方面不同:

  • 第一个查询(group by user),即 Update 查询:会更新先前输出的结果,即结果表流数据中 包含 INSERT 和 UPDATE 数据。小伙伴萌可以理解为 group by user 这条语句当中,输入源的数据是一直有的,源源不断的,同一个 user 的数据之后可能还是会有的,因此可以认为此 SQL 的每次的输出结果都是一个中间结果, 当同一个 user 下一条数据到来的时候,就要用新结果把上一次的产出中间结果(旧结果)给 UPDATE 了。所以这就是 UPDATE 查询的由来(其中 INSERT 就是第一条数据到来的时候,没有之前的中间结果,所以是 INSERT)。
  • 第二个查询(group by user, tumble(xxx)),即 Append 查询:只追加到结果表,即结果表流数据中 只包含 INSERT 的数据。小伙伴萌可以理解为虽然 group by user, tumble(xxx) 上游也是一个源源不断的数据,但是这个查询本质上是对时间上的划分,而时间都是越变越大的,当前这个滚动窗口结束之后,后面来的数据的时间都会比这个滚动窗口的结束时间大,都归属于之后的窗口了,当前这个滚动窗口的结果数据就不会再改变了,因此这条查询只有 INSERT 数据,即一个 Append 查询。

上面是 Flink SQL 连续查询处理机制上面的两类查询方式。我们可以发现连续查询的处理机制不一样,产出到结果表中的结果数据也是不一样的。针对上面两种结果表的更新方式,Flink SQL 提出了 changelog 表的概念来进行兼容。

changelog 表这个概念其实就和 MySQL binlog 是一样的。会包含 INSERTUPDATEDELETE 三种数据,通过这三种数据的处理来描述实时处理技术对于动态表的变更:

  • changelog 表:即第一个查询的输出表,输出结果数据不但会追加,还会发生更新。
  • changelog insert-only 表:即第二个查询的输出表,输出结果数据只会追加,不会发生更新。

7.SQL 流处理的输出:动态输出表转化为输出数据

可以看到我们的标题都是随着一个 SQL 的生命周期的。从 输入流映射为 SQL 动态输入表实时处理底层技术 - SQL 连续查询 到本小节的 SQL 动态输出表转化为输出数据。都是有逻辑关系的。

我们上面介绍到了连续查询的输出结果表是一个 changelog。其可以像普通数据库表一样通过 INSERTUPDATEDELETE 来不断修改。

它可能是一个只有一行、不断更新 changelog 表,也可能是一个 insert-onlychangelog 表,没有 UPDATEDELETE 修改,或者介于两者之间的其他表。

在将动态表转换为流或将其写入外部系统时,需要对这些不同状态的数据进行编码。Flink 的 Table API 和 SQL API 支持三种方式来编码一个动态表的变化:

  • 1️⃣ Append-only 流:输出的结果只有 INSERT 操作的数据。
  • 2️⃣ Retract 流
    • Retract 流包含两种类型的 message:add messagesretract messages。其将 INSERT 操作编码为 add message、将 DELETE 操作编码为 retract message、将 UPDATE 操作编码为更新先前行的 retract message 和更新新行的 add message,从而将动态表转换为 Retract 流。
    • Retract 流写入到输出结果表的数据如下图所示,有 -+ 两种,分别 - 代表撤回旧数据,+ 代表输出最新的数据。这两种数据最终都会写入到输出的数据引擎中。
    • 如果下游还有任务去消费这条流的话,要注意需要正确处理 -+ 两种数据,防止数据计算重复或者错误。

在这里插入图片描述

  • 3️⃣ Upsert 流
    • Upsert 流包含两种类型的 message:upsert messagesdelete messages。转换为 Upsert 流的动态表需要唯一键(唯一键可以由多个字段组合而成)。其会将 INSERTUPDATE 操作编码为 upsert message,将 DELETE 操作编码为 delete message
    • Upsert 流写入到输出结果表的数据如下图所示,每次输出的结果都是当前每一个 user 的最新结果数据,不会有 Retract 中的 - 回撤数据。
    • 如果下游还有一个任务去消费这条流的话,消费流的算子需要知道唯一键(即 user),以便正确地根据唯一键(user)去拿到每一个 user 当前最新的状态。其与 Retract 流的主要区别在于 UPDATE 操作是用单个 message 编码的,因此效率更高。下图显示了将动态表转换为 Upsert 流的过程。

在这里插入图片描述

8.补充知识:SQL 与关系代数

小伙伴萌会问到,关系代数是啥东西?

其实关系代数就是对于数据集(即表)的一系列的 操作(即查询语句)。常见关系代数有:

在这里插入图片描述
那么 SQL 和关系代数是啥关系呢?

SQL 就是能够表示关系代数一种面向用户的接口:即 用户能使用 SQL 表达关系代数的处理逻辑,也就是我们可以用 SQL 去在表(数据集)上执行我们的业务逻辑操作(关系代数操作)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1514906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows Server 各版本搭建 Web 服务器实现访问本地 Web 网站(03~19)

一、Windows Server 2003 点击左下角开始➡管理工具➡管理您的服务器,点击添加或删除角色 点击下一步 选择自定义,点击下一步 选择应用程序服务器,点击下一步 不勾选,点击下一步 这里提示插入磁盘,咱们提前下载好 IIS…

SinoDB海洋渔业时序数据解决方案

一、海洋渔业平台 介绍 福建理工大学针对我国浅海增养殖信息化和智能化程度低、多源数据库缺乏、大数据挖掘与分析技术薄弱等问题,构建了海洋渔业平台。 该平台方案使用了星瑞格数据库管理系统(下文简称:SinoDB),充分利…

在Linux中进行OpenSSH升级

由于OpenSSH有严重漏洞,因此需要升级OpenSSH到最新版本。 OpenSSL和OpenSSH都要更新,OpenSSH依赖于OpenSSL。 第一步,查看当前的OpenSSH服务版本。 命令:ssh -V 第二步,安装、启动telnet,关闭安全文件&a…

使用CrossOver 在Mac 运行Windows 软件|D3DMetal是什么技术,

CrossOver Mac 使用特点 • 免费试用 14 天,可使用 CrossOver Mac 全部功能,• 试用过期会保留之前安装的 Windows 软件• 使 Mac 运行 Windows 程序 使用CrossOver在Mac上运行Windows软件是一个方便且无需安装完整Windows操作系统的解决方案。CrossOve…

Linux下的编辑器——Vim

vi/vim 的区别简单点来说,它们都是多模式编辑器,不同的是 vim 是 vi 的升级版本,它不仅兼容 vi 的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window…

SpringBoot(Lombok + Spring Initailizr + yaml)

1.Lombok 1.基本介绍 2.应用实例 1.pom.xml 引入Lombok&#xff0c;使用版本仲裁 <!--导入springboot父工程--><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version&g…

20240313寻找集成联调交付的具体方式

集成联调交付&#xff08;Integrated Joint Debugging and Delivery&#xff09;是软件开发过程中的一个阶段&#xff0c;主要涉及将不同的软件模块或组件整合在一起&#xff0c;并进行联合调试和测试&#xff0c;以确保它们能够作为一个整体正常工作。这个过程通常发生在开发周…

DMSP夜间灯光卫星介绍和数据下载

DMSP(Defense Meteorological Sate-llite Program)是美国国防部的极轨卫星计划&#xff0c;与NOAA卫星同属于一类&#xff0c;只不过星上载荷不同。 DMSP卫星简介 现有DMSP为三轴姿态稳定卫星&#xff0c;运行在高度约830km的太阳同步轨道&#xff0c;周期约101min&#xff0c…

安卓六大布局

LinearLayout&#xff08;线性布局&#xff09; 1.简介 线性布局在开发中使用最多&#xff0c;具有垂直方向与水平方向的布局方式。LinearLayout 默认是垂直排列的&#xff0c;但是可以通过设置 android:orientation 属性来改变为水平排列。 2.常用属性 orientation&#xf…

docker修改配置文件后一直显示Restarting (1) 状态

docker修改配置文件后一直显示Restarting 状态 一、问题描述 一、问题描述 当我在修改nginx的配置文件之后&#xff0c;一直出现Restarting 状态&#xff0c;并且无法成功访问&#xff0c;如下图所示 然后查看nginx的日志&#xff0c;如下所示&#xff1a; 因为我修改的时配…

华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验

如图所示&#xff0c;由于业务需要&#xff0c;用户有访问Internet的需求。 用户通过接入层交换机SwitchB和核心层交换机SwitchA以及接入网关Router与Internet进行通信。为了保证数据和网络的安全性&#xff0c;用户希望保证Internet到服务器全部流量的安全性&#xff0c;配置重…

【零基础学习05】嵌入式linux驱动中platform与设备树基本实现

大家好,为了进一步提升大家对实验的认识程度,每个控制实验将加入详细控制思路与流程,欢迎交流学习。 今天主要学习一下,基于总线、设备和驱动进行匹配的平台驱动模型,这次将采用设备树的platform设备与驱动的编写方法,目前绝大多数的Linux内核已经支持设备树,这次主要来…

【Flutter 面试题】在Flutter中如何处理用户输入和手势操作?

【Flutter 面试题】在Flutter中如何处理用户输入和手势操作&#xff1f; 文章目录 写在前面解答补充说明完整代码示例运行结果详细说明 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff0c;GitChat专栏作者&#xff0c;阿里云社区专家…

用Python编写自己的微型Redis

前几天我想到,写一个简单的东西会很整洁 雷迪斯-像数据库服务器。虽然我有很多 WSGI应用程序的经验,数据库服务器展示了一种新颖 挑战,并被证明是学习如何工作的不错的实际方法 Python中的套接字。在这篇文章中,我将分享我在此过程中学到的知识。 我项目的目的是 编写一个简单…

基于大数据的商业模式创新研究

目录 一、导论 2 &#xff08;一&#xff09;研究背景 2 &#xff08;二&#xff09;研究意义 2 &#xff08;三&#xff09;研究内容 3 &#xff08;四&#xff09;研究思路与研究方法 4 &#xff08;五&#xff09;国内外研究现状 6 二、大数据的界定与应用概况 7 &#xff…

【Android】源码中的建造者模式

本文是基于 Android 14 的源码解析 在 Android 源码中&#xff0c;最常用到的建造者模式就是 AlertDialog.Builder&#xff0c;使用该建造者来构建复杂的 AlertDialog 对象。在开发过程中&#xff0c;我们经常用到 AlertDialog&#xff0c;具体示例如下&#xff1a; private f…

Linux_网络项目_WEB服务器 处理服务器写入失败后sigpipe信号导致服务器崩溃退出问题,引入线程池缓解大量请求,服务器组件化重构,在线计算机业务测试

文章目录 1. 处理服务器写入管道出错2. 引入线程池缓解大量请求导致服务器崩溃设计线程任务类单例线程池组件设计 3.代码位置4. 在线计算机业务运行截图 1. 处理服务器写入管道出错 经过测试&#xff0c;服务器在读取报文时如果出错可以选择直接关闭这个TCP里链接来节省资源。…

界面开发框架DevExpress XAF v24.1新版预告 - 跨平台应用UI(二)

DevExpress XAF是一款强大的现代应用程序框架&#xff0c;允许同时开发ASP.NET和WinForms。XAF采用模块化设计&#xff0c;开发人员可以选择内建模块&#xff0c;也可以自行创建&#xff0c;从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 本文中的内容概述了…

Toy 语言到 LLVM IR 实现源码注释

对从程序源代码到AST的转换部分做了注释 源码&#xff1a; toy.cpp #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Ver…

Java Day9 Stream流

Stream流 1、认识2、Stream流使用步骤3、如何获取Stream流4.Stream流的中间方法5、 Stream流终结方法 1、认识 2、Stream流使用步骤 3、如何获取Stream流 //list获取stream流List<String> listnew ArrayList<>();Collections.addAll(list,"崔十一","…