探知FlinkSQL背后默默支撑的“男人们“

flink JdbcCatalog使用中的一个注意事项 flink sql通过JdbcCatalog连接postgresql踩坑记录 flink sql可以通过JdbcCatalog连接postgresql数据库,从而实现直接对postgresql表的相关操作,相关代码如下: StreamExecutionEnvironment bsEnv = StreamExecutionEnvironment.getExecutionEnvironment(); EnvironmentSettings bsSettings = Environ 阅读详情

​

 

主要内容

本篇主要从FlinkSQL实现的内核与原理,工作流等的视角带大家构建一幅FlinkSQL全景图(以Blink为主介绍),探知背后支撑的“男人们”(组件)。建议收藏,仅此一份。

主要内容:

1. Table API 与 SQL

2. Apache Calcite

3. 元数据

4. SQL 函数

5. Flink Planner 与 Blink Planner

6. Blink SQL执行过程

7. SQL优化器

8. 总结

Table API 与 Table SQL

Table API 和 Table SQL 集成在同一套 API 中。这套 API 的核心概念是Table,用作查询的输入和输出。

Apache Flink 具有两个关系型 API - Table API 和 Table SQL - 用于统一的流和批处理。Table API 是 Scala 和 Java 的语言集成查询 API,它允许用非常直观的方式从关系运算符(如选择、过滤和连接)组成查询。Flink 的 SQL 支持是基于 Apache Calcite,它实现了 SQL 标准。无论输入是批处理输入(DataSet)还是流输入(DataStream),在任一接口中指定的查询都具有相同的语义,并指定相同的结果。

Table API 和 SQL 接口与 Flink 的 DataStream 和 DataSet API 紧密集成。你可以很容易地在所有 API 和建立在 API 基础上的库之间切换。

Apache Calcite

Calcite 是什么

Apache Calcite是一款开源的动态数据管理框架,它提供了标准的 SQL 语言、多种查询优化和连接各种数据源的能力,但不包括数据存储、处理数据的算法和存储元数据的存储库。

Calcite采用的是业界大数据查询框架的一种通用思路,它的目标是“one size fits all(一种方案适应所有需求场景)”,希望能为不同计算平台和数据源提供统一的查询引擎。

Calcite作为一个强大的SQL计算引擎,在Flink内部的SQL引擎模块就是基于Calcite。

Calcite 的特点

  • 支持标准SQL语言;

  • 独立于编程语言和数据源,可以支持不同的前端和后端;

  • 支持关系代数、可定制的逻辑规则和基于成本模型优化的查询引擎;

  • 支持物化视图(materialized view)的管理(创建、丢弃、持久化和自动识别);

  • 基于物化视图的Lattice和Tile机制,以应用于OLAP分析;

  • 支持对流数据的查询。

Calcite 的功能

1. SQL 解析

Calcite 的SQL解析是通过JavaCC实现的,使用JavaCC编写SQL语法描述文件,将SQL解析成未经校验的AST语法树。

2. SQL 校验

无状态的校验:验证SQL语句是否符合规范。有状态的校验:通过与元数据结合验证SQL的Schema,Field,Function是否存在,输入和输出是否符合。

3. 查询优化

对RelNode和逻辑计划树进行优化,得到优化后的生成物理执行计划。

4. SQL 生成器

将物理执行计划生成特定平台的可执行程序,比如Flink,Hive,不同规则的SQL查询语句。

5. 执行

通过各个执行平台在内存中编译,然后执行查询。

FlinkSQL 结合 Calcite

一条SQL从提交到Calcite解析,优化,到最后的Flink执行,一般分以下过程:

1. Sql Parser: 将sql语句通过java cc解析成AST(语法树),在calcite中用SqlNode表示AST;

2. Sql Validator: 结合数字字典(catalog)去验证sql语法;

3. 生成Logical Plan: 将sqlNode表示的AST转换成LogicalPlan, 用relNode表示;

4. 生成 optimized LogicalPlan: 先基于calcite rules 去优化logical Plan,基于flink定制的一些优化rules去优化logical Plan;

5. 生成Flink PhysicalPlan: 这里也是基于flink里头的rules将,将optimized LogicalPlan转成成Flink的物理执行计划;

6. 将物理执行计划转成Flink ExecutionPlan: 就是调用相应的tanslateToPlan方法转换和利用CodeGen元编程成Flink的各种算子。

Table API 来提交任务的话,基本流程和运行SQL类似,稍微不同的是:table api parser: flink会把table api表达的计算逻辑也表示成一颗树,用treeNode去表式; 在这棵树上的每个节点的计算逻辑用Expression来表示。

简单说一下SQL优化:RBO(基于规则)

RBO主要是开发人员在使用SQL的过程中,有些发现有些通用的规则,可以显著提高SQL执行的效率,比如最经典的filter下推:

将Filter下推到Join之前执行,这样做的好处是减少了Join的数量,同时降低了CPU,内存,网络等方面的开销,提高效率。

SQL优化的发展,则可以分为两个阶段,即RBO(基于规则),和CBO(基于代价)

RBO和CBO的区别大概在于: RBO只为应用提供的rule,而CBO会根据给出的Cost信息,智能应用rule,求出一个Cost最低的执行计划。需要纠正很多人误区的一点是,CBO其实也是基于rule的,接触到RBO和CBO这两个概念的时候,很容易将他们对立起来。但实际上CBO,可以理解为就是加上Cost的RBO。

元数据

Catalog 提供了元数据信息,例如数据库、表、分区、视图以及数据库或其他外部系统中存储的函数和信息。

数据处理最关键的方面之一是管理元数据。元数据可以是临时的,例如临时表、或者通过 TableEnvironment 注册的 UDF。元数据也可以是持久化的,例如 Hive Metastore 中的元数据。Catalog 提供了一个统一的API,用于管理元数据,并使其可以从 Table API 和 SQL 查询语句中来访问。

1. 目前支持的类型

(1) GenericInMemoryCatalog

是基于内存实现的 Catalog,所有元数据只在 session 的生命周期内可用。

(2) JdbcCatalog

JdbcCatalog 使得用户可以将 Flink 通过 JDBC 协议连接到关系数据库。PostgresCatalog 是当前实现的唯一一种 JDBC Catalog。

(3) HiveCatalog

HiveCatalog 有两个用途:作为原生 Flink 元数据的持久化存储,以及作为读写现有 Hive 元数据的接口。

(4) 用户自定义 Catalog

Catalog 是可扩展的,用户可以通过实现 Catalog 接口来开发自定义 Catalog。想要在 SQL CLI 中使用自定义 Catalog,用户除了需要实现自定义的 Catalog 之外,还需要为这个 Catalog 实现对应的 CatalogFactory 接口。

CatalogFactory 定义了一组属性,用于 SQL CLI 启动时配置 Catalog。这组属性集将传递给发现服务,在该服务中,服务会尝试将属性关联到 CatalogFactory 并初始化相应的 Catalog 实例。

2. 元数据分类

catalog定义主要有三种数据类型接口,也就是常用到的数据库,表&视图,函数。当然还有最上层的Catalog容器。

(1) 数据库

等同于数据库中库的实例,接口定义为CatalogDatabase,定义数据库实例的元数据,一个数据库实例中包含表,视图,函数等多种对象。

(2) 表&视图

CatalogTable对应数据库中的表,CatalogView队形数据库中的视图。

表是一种存储的实体,包换了字段信息,表的分区,属性,描述信息。其实说白了字段定义和之前印象的数据库很是类似。你可以对比过来。不同的是,拿flink来说,所有的表都是外部数据源,除了上面所说的,还需要访问信息,比如IP端口,mater地址,connector连接类等等。

视图是一个虚拟概念,本质上是一条SQL查询语句,底层对应一张表或者多张表。包含SQL查询语句,视图的字段信息,视图的属性等等的信息。

(3) 函数

CatalogFunction是函数元数据的接口。函数元数据包含了所在的类信息和编程语言。

3. 数据访问

Flink的Table API和SQL程序可以连接到其他外部系统,用于读和写批处理表和流表。source table提供对存储在外部系统(如数据库、消息队列或文件系统)中的数据的访问。sink table 向外部存储系统发送表。根据source和sink器的类型,它们支持不同的格式,如CSV、Avro、Parquet或ORC。

(1) TableSchema

Table Source 和 Sink需要具备对外数据源的描述能力,所以Flink定义了TableSchema对象来定义字段名称和字段类型,存储格式等等信息

(2) 时间属性

支持处理时间和时间时间

(3) Watermark

用来处理乱序的数据。

4. Table Source & Table Sink

Flink本地支持各种连接器,可以查看往期总结

  • Filesystem

  • Elasticsearch

  • Apache Kafka

  • Amazon Kinesis Data Streams

  • JDBC

  • Apache HBase

  • Apache Hive

几个主要Table Source与Sink体系

(1) StreamTableSource

流数据抽象,区分了无界数据与有界数据。

(2) LookupableTableSource

按照Join条件中的字段进行关联。

(3) FilterableTableSource

过滤不符合条件的记录。

(4) LimitableTableSource

限制记录条数。

(5) ProjectableTableSource

过滤不会被使用的字段。

(6) AppendStreamTableSink

追加模式的TableSink 支持追加,不支持更新。

(7) RetractStreamTableSink

支持召回模式的TableSink,召回模式其实就是流上的update。

(8) UpsertStreamTableSink

有则更新,无则插入

SQL 函数

临时函数和持久化函数。临时函数始终由用户创建,它容易改变并且仅在会话的生命周期内有效。持久化函数不是由系统提供,就是存储在 Catalog 中,它在会话的整个生命周期内都有效。

内置函数

Table API和SQL为用户提供了一组用于数据转换的内置函数。如果您需要的函数还不受支持,您可以实现用户定义的函数

(1) Comparison Functions(比较型函数)

  eg:value1 = value2

(2) Logical Functions(逻辑函数)

  eg: boolean1 OR boolean2

(3) Arithmetic Functions(算术函数)

 eg: numeric1 + numeric2

(4) String Functions(字符串函数)

UPPER(string)

(5) Temporal Functions(时间函数)

YEAR(date)

(6) Conditional Functions(有条件的函数)

IF(condition, true_value, false_value)

(7) Type Conversion Functions(类型转换函数)

CAST(value AS type)

(8) Collection Functions(集合函数)

array '[' INT ']'

(9) Value Construction Functions  , Value Access Functions,Grouping Functions,Hash Functions,Auxiliary Functions,Aggregate Functions,Column Functions (不一一列举)

自定义函数

(1) 标量函数(UDF)

标量函数 将标量值转换成一个新标量值,也就是对一行数据中的一个或者多个字段返回一个单值。

(2) 聚合函数(UDAGG)

自定义聚合函数(UDAGG)是把一个表(一行或者多行,每行可以有一列或者多列)聚合成一个标量值。

(3) 表值函数(UDTF)

表值函数 将标量值转换成新的行数据。可以接收一个或者多个字段作为参数,输出多行列数据。

(4) 表值聚合函数(UDTAGG)

自定义表值聚合函数(UDTAGG)可以把一个表(一行或者多行,每行有一列或者多列)聚合成另一张表,结果中可以有多行多列。

(5) 异步表值函数

异步表值函数 是异步查询外部数据系统的特殊函数。

Planner 与 Blink Planner

Flink Table/SQL体系中的Planner(即查询处理器)是沟通Flink与Calcite的桥梁,为Table/SQL API提供完整的解析、优化和执行环境。

Flink Table 的新架构实现了查询处理器的插件化,项目完整保留原有 Flink Planner (Old Planner),同时又引入了新的 Blink Planner,用户可以自行选择使用 Old Planner 还是 Blink Planner。

主要区别:

  • Blink做到了真正的流批统一,即将批看做是特殊的流,把处理批的API和处理流的API做成了一样的。也就是说不管是批数据还是流数据,底层统统都是DataStream。所以使用Blink作为table planner的程序,Table和DataSet是不能相互转换的。

  • Blink planner是不支持BatchTableSource的,它只支持StreamTableSource。

  • Blink Planner和Old Planner的FilterableTableSource是不兼容的。Old - Planner会下推PlannerExpression到FilterableTableSource。而Blink planner下推的是Expression。

  • 基于String的键值对配置项只能用于Blink Planner

  • Blink Planner会优化多个sink到同一个TableEnvironment和StreamTableEnvironment。而Old Planner会为不同的sink优化到自己的DAG中,也就是说有几个sink就有几个DAG。

  • Old Planner 不支持 catalog统计,Blink支持。

  • Old Planner 不支持版本表(versioned Table)。版本表类似HBASE中版本表的意思,每个key可以记住过去的几个值。

Blink SQL执行过程

SQL执行过程分三个阶段

(1) 从SQL到 Operation

(2) 从Operation 到 Transformation

(3) 环境的执行阶段

从SQL到 Operation

(1) 解析SQL转换为QueryOperation;

(2) SQL解析为SqlNode;

(3) 校验SqlNode;

(4) 调用Calcite SQLToRelConvertrt将SqlNode转化为RelNode逻辑树;

(5) RelNode转化为Operation。

Operation 到 Transformation

(1) DQL(数据查询语言)转换,在flink中作为中间运算;

(2) DML(数据操作语言),DQL转换。

整个转换从Operation开始,先转换为Calcite的逻辑计划树,再转化为Flink的逻辑计划树,然后进行优化。优化后的逻辑树转换为Flink的物理执行,物理执行生成一系列的算子,udf等等,包装到Transformation中。

环境的执行阶段

有了Transformation后正式进入到StreamGraph的过程中,最终交给Flink集群去运行。

SQL优化器

查询优化器

再次提到两个优化器:RBO(基于规则的优化器) 和 CBO(基于代价的优化器)

(1) RBO(基于规则的优化器)会将原有表达式裁剪掉,遍历一系列规则(Rule),只要满足条件就转换,生成最终的执行计划。一些常见的规则包括分区裁剪(Partition Prune)、列裁剪、谓词下推(Predicate Pushdown)、投影下推(Projection Pushdown)、聚合下推、limit下推、sort下推、常量折叠(Constant Folding)、子查询内联转join等。

(2) CBO(基于代价的优化器)会将原有表达式保留,基于统计信息和代价模型,尝试探索生成等价关系表达式,最终取代价最小的执行计划。CBO的实现有两种模型,Volcano模型,Cascades模型。这两种模型思想很是相似,不同点在于Cascades模型一边遍历SQL逻辑树,一边优化,从而进一步裁剪掉一些执行计划。

目前各大数据库和计算引擎倾向于CBO。

总结

在目前情况下,在阿里对Flink社区的贡献下,Flink包含了Flink SQL 和 Blink SQL体系,Flink Planner称之为 Old Planner,Blink Planner称之为 New Planner。从中可以发现 Blink Planner是未来,Flink Planner将会被淘汰。

FlinkSQL依靠 Calcite提供了一套SQL验证,解析,优化等等操作。同时FlinkSQL提供元数据管理,SQL函数,数据源的建设。也自由化地提供了自定义函数,自定义connector连接,丰富了场景的使用。

FlinkSQL你值得拥有!!!

 

大数据左右手

技术如同手中的水有了生命似的,汇聚在了一起。作为大数据开发工作者,致力于大数据技术的学习与工作,分享大数据原理、架构、实时、离线、面试与总结,分享生活思考与读书见解。总有适合你的那一篇。

关注公众号!!!

和我联系吧,加群交流大数据知识,一起成长~~~

详解Flink SQL实现原理 一、目标数据 随着移动支付的普及,电商网站不断涌现,由于电商网站产品太多,由用户产生的评论数据就更多了,这次我们以京东为例,针对某一单品的评论数据进行数据采集,并且做简单数据分析。 二、页面分析 这个是某一手机页面的详情页,对应着手机的各种参数以及用户评论信息,页面URL是: https://item.jd.com/10022971060622.html#none 然后通过分析找到评论数据对应的数据接口,如下图所示: 它的请求url: https://club.jd 阅读详情

相关推荐

Flink Catalogs 如何玩转元数据中心?

产生背景 在flink 1.11.0 之前,用户如果依赖 Flink 的 source/sink 读写关系型数据库表或者读取 changelog 时,必须要手动创建对应的 schema。但是这样会有一个问题,当数据库中的 schema 发生变化时,也需要手动更新对应的 Flink 任务以保持类型匹配,任何不匹配都会造成运行时报错使作业失败。 操作冗余且繁琐,体验极差。 实际上对于任何和 Flink 连接的外部系统都可能有类似的上述问题! 1.11.0 版本后,用户使用 Flink SQL 时可以自动获取表的

penriver的博客 1703

Flink Catalog

Flink提供了基础的Catalog接口,自定义Catalog实现此接口即可此外还有一个CatalogFactory接口,用于创建Catalog。

不甚了然的博客 608

java设计模式CatalogDAOFactory是典型的工厂方法

工厂模式定义:提供创建对象的接口. 为何使用? 工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。 为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。 我们以类Sample为例, 如果我们要创建Sample的实例对象: Sample sample=new Sample(); 可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等。 首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成: Sample sample=new Sample(参数); 但是,如果创建sample实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重整)。 为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。 在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。 这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.现在Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下: Sample mysample=new MySample(); Sample hissample=new HisSample(); 随着项目的深入,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的. 但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了. 工厂方法 你会建立一个专门生产Sample实例的工厂: public class Factory{   public static Sample creator(int which){   //getClass 产生Sample 一般可使用动态类装载装入类。   if (which==1)     return new SampleA();   else if (which==2)     return new SampleB();   } } 那么在你的程序中,如果要实例化Sample时.就使用 Sample sampleA=Factory.creator(1); 这样,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵. 使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类,用来生成产品Sample,如下图,最右边是生产的对象Sample: 进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类concreteFactory了。 抽象工厂 工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory). 这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2. 这里假设:Sample有两个concrete类SampleA和SamleB,而Sample2也有两个concrete类Sample2A和SampleB2 那么,我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现,下面就是将上例中的Factory拓展成抽象工厂: public abstract class Factory{   public abstract Sample creator();   public abstract Sample2 creator(String name); } public class SimpleFactory extends Factory{   public Sample creator(){     .........     return new SampleA   }   public Sample2 creator(String name){     .........     return new Sample2A   } } public class BombFactory extends Factory{   public Sample creator(){     ......     return new SampleB   }   public Sample2 creator(String name){     ......     return new Sample2B   } } 从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产Sample和Sample2? 抽象工厂还有另外一个关键要点,是因为 SimpleFactory内,生产Sample和生产Sample2的方法之间有一定联系,所以才要将这两个方法捆绑在一个类中,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以名称叫SimpleFactory。 在实际应用中,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用, 举例 我们以Jive的ForumFactory为例,这个例子在前面的Singleton模式中我们讨论过,现在再讨论其工厂模式: public abstract class ForumFactory {   private static Object initLock = new Object();   private static String className = "com.jivesoftware.forum.database.DbForumFactory";   private static ForumFactory factory = null;   public static ForumFactory getInstance(Authorization authorization) {     //If no valid authorization passed in, return null.     if (authorization == null) {       return null;     }     //以下使用了Singleton 单态模式     if (factory == null) {       synchronized(initLock) {         if (factory == null) {             ......           try {               //动态转载类               Class c = Class.forName(className);               factory = (ForumFactory)c.newInstance();           }           catch (Exception e) {               return null;           }         }       }     }     //Now, 返回 proxy.用来限制授权对forum的访问     return new ForumFactoryProxy(authorization, factory,                     factory.getPermissions(authorization));   }   //真正创建forum的方法由继承forumfactory的子类去完成.   public abstract Forum createForum(String name, String description)   throws UnauthorizedException, ForumAlreadyExistsException;   .... } 因为现在的Jive是通过数据库系统存放论坛帖子等内容数据,如果希望更改为通过文件系统实现,这个工厂方法ForumFactory就提供了提供动态接口: private static String className = "com.jivesoftware.forum.database.DbForumFactory"; 你可以使用自己开发的创建forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以. 在上面的一段代码中一共用了三种模式,除了工厂模式外,还有Singleton单态模式,以及proxy模式,proxy模式主要用来授权用户对forum的访问,因为访问forum有两种人:一个是注册用户 一个是游客guest,那么那么相应的权限就不一样,而且这个权限是贯穿整个系统的,因此建立一个proxy,类似网关的概念,可以很好的达到这个效果. 看看Java宠物店中的CatalogDAOFactory: public class CatalogDAOFactory {   /**   * 本方法制定一个特别的子类来实现DAO模式。   * 具体子类定义是在J2EE的部署描述器中。   */   public static CatalogDAO getDAO() throws CatalogDAOSysException {     CatalogDAO catDao = null;     try {       InitialContext ic = new InitialContext();       //动态装入CATALOG_DAO_CLASS       //可以定义自己的CATALOG_DAO_CLASS,从而在无需变更太多代码       //的前提下,完成系统的巨大变更。       String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);       catDao = (CatalogDAO) Class.forName(className).newInstance();     } catch (NamingException ne) {       throw new CatalogDAOSysException("         CatalogDAOFactory.getDAO: NamingException while           getting DAO type : \\n" + ne.getMessage());     } catch (Exception se) {       throw new CatalogDAOSysException("         CatalogDAOFactory.getDAO: Exception while getting           DAO type : \\n" + se.getMessage());     }     return catDao;   } } CatalogDAOFactory是典型的工厂方法,catDao是通过动态类装入器className获得CatalogDAOFactory具体实现子类,这个实现子类在Java宠物店是用来操作catalog数据库,用户可以根据数据库的类型不同,定制自己的具体实现子类,将自己的子类名给与CATALOG_DAO_CLASS变量就可以。 由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化。

calcite在flink源码中入口以及sql怎么转换StreamGraph?

sql转换为streaming,calcite入口

qq_34492129的博客 1125

MFC 修改CheckBox的文本颜色方法

设置主题 这一步是必须的,不可省略。 BOOL CMFCApplication1Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 // 设置主题 HWND

Kim的博客 2249

SIMULIA-Simpack 2022x新功能介绍

增加库伦摩擦类型力元95 Coulomb Friction增加了3种新的摩擦方向类型用于模拟平面、圆柱和球面摩擦。针对平移和旋转摩擦改进了滑动到粘着过渡阶段的检测,增加一个参数定义两种不同的滑移-粘滞过渡模式,即“Unloaded stick stiffness”和“Preload stick with last slip”。新增加124'Applied Load’力元允许用户将力或扭矩作为恒定值或通过激励元素施加到To Marker点上。该力元建模操作方便,效率高。支持线性柔性体装配。

crystalzhan的博客 1047

flink catalogs --- flink-1.12

flink hive catalogs

chbxw 1664

Contest 226 - C - Martial artist

from atcoder Problem Statement Time Limit: 2 sec / Memory Limit: 1024 MB Score :300300points Takahashi is a martial artist. There areNNmoves that a martial artist can learn, called Move11,22,\ldots…,NN. For each1 \leq i \leq N1≤i≤N, it takes...

m0_54674275的博客 1020

Flink之Catalog

Catalog是一种用于管理和组织元数据的抽象。Catalog提供了元数据信息,例如数据库、表、分区、视图以及数据库或其他外部系统中存储的函数和信息。

积跬步,至千里。 2852

antv x6 沿边图标循环动画实现

2.使用transition给边设置动画,利用complte方法实现循环动画。实现效果,如下图,边上存在两个图标,要求图标延边一直循环动画。1.注册一个自定义边,边上定义两个图标,并设置其初始位置。

lingliu0824的博客 3366

Penpot自托管全攻略:5分钟搞定私有化部署(附Docker配置详解)

本文详细介绍了Penpot开源原型设计工具的私有化部署全流程,从Docker基础配置到企业级优化方案。通过分步指南和实战技巧,帮助设计团队快速搭建安全高效的自托管环境,实现数据自主可控。内容涵盖LDAP集成、性能监控、备份策略等关键企业需求,是Penpot私有化部署的完整参考手册。

sugar的博客 1135

1.18.3.Flink Catalog介绍、Catalog 定义、Catalog 的实现、Catalog 使用举例

1.18.3.Flink Catalog介绍 1.18.3.1.引言 1.18.3.2.Catalog 定义 1.18.3.3.Catalog 的实现 1.18.3.4.Catalog 使用举例 1.18.3.Flink Catalog介绍 1.18.3.1.引言 以下转自:http://legendtkl.com/2020/07/26/flink-catalog/ 这篇文章我们介绍了一下 Flink 的 Catalog,基于 Flink 1.11,熟悉 Flink 或者 Spark 等大数据引擎的同学应该

涂作权的博客 8217

mediasoup源码分析(二十)服务端架构设计

目录 简介 信令服务(房间服务) 调度服务 媒体服务 简介 流媒体服务器大的方向上可以分为上述三个模块。目前行业内都是分布式服务,独立部署。mediasoup信令与媒体之间虽然可以管道通信。但在行业内,服务之间通过管道通信用的少。 一般是rpc、mq,或者传统的tcp。这块licode架构比较不错,licode是信令和媒体服务通过MQ消息队列解耦。 下面介绍一下这三个服务主要功能,当然文中所说也是一家之言。 信令服务(房间服务) 信令服务也称为房间服务。有的企业把信令和房间分开,信..

lcalqf的专栏 1545

flink hive 异常以及解决办法

[ERROR] Could not execute SQL statement. Reason: java.lang.NoClassDefFoundError: Could not initialize class org.apache.flink.table.catalog.hive.factories.HiveCatalogFactoryOptions 原因:缺失依赖 解决办法: 新增hive-exec-3.1.0.jar 依赖 [ERROR] Could not execute SQL state

HiBoyljw的博客 3025

用 Custom Entity 打造 RAP Value Help:从能跑到好用的深度踩坑笔记

本文介绍了在RAP项目中实现Value Help(Fiori输入帮助)的完整流程。通过Custom Entity方式,开发者可以灵活构建不依赖数据库实体的值帮助功能,但需手动实现CDS原本提供的过滤、排序、分页等能力。文章以一个典型场景为例,详细说明了如何为Partner维护界面的City字段创建可搜索的值帮助,包括创建查询实现类、绑定CDS Custom Entity、服务发布等关键步骤,并特别指出了处理排序分页请求等常见问题。最后强调在ABAP Cloud环境下需要自行实现查询能力,而非依赖传统工具类。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 141

出现Command ‘vim‘ is available in the following places,vim: command not found等解决方法

内置命令无法识别,说明系统变量有误,导致无法识别,既然系统变量有误,将其注释或者更改为正确的即可,但是现在打不开,又怎么注释掉。替换vim来打开编辑,打开之前错误的全局变量文件,发现变量有误,要么注释要么改为。系统变量有全局变量(通过命令行printenv或者echo)和局部变量。对应通过vim修改错误的变量文件,不然source也无法让配置文件生效。本身vim是系统内置的命令,连vim都出现问题。修改为正确的即可,之后还需要重启服务器,使用。之后即可成功,通过即可查看命令是否有写入。...

码农研究僧的博客 5884

报错:Could not find a suitable table factory for ‘org.apache.flink.table.factories.TableSourceFactory

重要错误提示:这是在提交yarn时报的错误,原因其实就是少了一些包,提交的集群后一些依赖包使用flink的lib目录下的,所以我需要将一些依赖包放到lib目录下。我们看到缺少的是org.apache.flink.table.factories.TableSourceFactory类,所以对应的应该是flink连接JDBC的包。这里我们去官网上下载你对应flink版本的连接JDBC的包,如下图: 放到提交集群的客户机部署的flink的lib目录下。可以看到上面最主要的是缺少依赖包,其实像很多类似的错误都是由于

Chenftli的博客 5512

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

flink集成hive中遇到的问题以及解决方案

版本: 1)hadoop:2.7.2 2)hive:2.3.4 3)flink:1.11.2 4)os:centos 7.5 1. 首先集成hadoop 1.1 添加如下依赖,因为会有jar包冲突的问题,注意jar包的 ,以及jar包的 ,否则会报类似 hadoop.config找不到的错误 <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.flink/flink-connector-hive --&

leoma2012的博客 4270

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

大数据计算-SQL优化手段(CBO)-以Flink为例

展示CBO规则是如何在flink SQL里运行的

csdn问鼎 743

个推基于Flink SQL建设实时数仓实践

作为一家数据智能企业,个推在服务垂直行业客户的过程中,会涉及到很多数据实时计算和分析的场景,比如在服务开发者时,需要对App消息推送的下发数、到达数、打开率等后效数据进行实时统计;在服务政府单位时,需要对区域内实时人口进行统计和画像分析。为了更好地支撑大数据业务发展,个推也建设了自己的实时数仓。相比Storm、Spark等实时处理框架,Flink不仅具有高吞吐、低延迟等特性,同时还支持精确一次语义(exactly once)、状态存储等特性,拥有很好的容错机制,且使用门槛低、易上手、开发难度小。因此,个推主

个推技术学院 2251

11、Flink Table API & SQL - Catalogs(使用概览和样例)

Catalogs提供了元数据,例如数据库、表、分区、视图、函数和访问存储在数据库或其他外部系统中的数据所需的信息。 数据处理最重要的方面之一是管理元数据。它可以是临时表之类的临时元数据,也可以是针对表环境注册的UDF函数。或者永久的元数据,比如Hive中的元数据。Catalogs提供了一个统一的API来管理元数据,并可以通过表API和SQL查询。 Catalog Types GenericI...

主要写大数据集群一线运维和学习工作经验 6817

Flink自定义函数之表值聚合函数(UDTAGG函数)

自定义表值聚合函数(UDTAGG)可以把一个表(一行或者多行,每行有一列或者多列)聚合成另一张表,结果中可以有多行多列。理解:假设有一个饮料的表,这个表有 3 列,分别是 id、name 和 price,一共有 5 行。假设你需要找到价格最高的两个饮料,类似于 top2() 表值聚合函数。你需要遍历所有 5 行数据,结果是有 2 行数据的一个表。

marui156的专栏 1221

Flink自定义函数之聚合函数(UDAGG函数)

聚合函数:将一个表的一个或多个行并且具有一个或多个属性聚合为标量值。聚合函数理解:假设一个关于饮料的表。表里面有三个字段,分别是 id、name、price,表里有 5 行数据。假设你需要找到所有饮料里最贵的饮料的价格,即执行一个 max() 聚合。你需要遍历所有 5 行数据,而结果就只有一个数值。

marui156的专栏 1708

Flink 聚合函数

用户定义的聚合函数(UDAGG)将一个表(一个或多个具有一个或多个属性的行)聚合为标量值。上图显示了聚合的示例。假设您有一个包含饮料数据的表格。该表由三列的id,name...

ItStar 2778

flink 1.9 sql-client 连接hive catalog配置

一,下载flink 1.9 或编译flink 1.9 下载地址:https://www.apache.org/dyn/closer.lua/flink/flink-1.9.0/flink-1.9.0-bin-scala_2.11.tgz flink 1.9 编译或特殊版本编译(如cdh ,Hortonworks等)参考另一篇文章 https://blog.youkuaiyun.com/h33514650...

h335146502的专栏 7296

Flink catalog简单使用

FlinkCatalog使用demo

3.4的博客 1468
上一篇: Kafka面试准备,收藏这一篇就够了!!!
下一篇: Flink执行流程与源码分析(面试必问,建议收藏)
大数据左右手
博客等级 码龄9年 475粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值