00:00
接下来我们来介绍一下table API和liq中的数,对于数概念其实我们已经非常熟悉了,在数学当中所谓的函数呢,那其实应该是。Y等于FX这样的一种映射关系啊,那就是我们所说的,如果画出一个图像的话。横坐标是X,纵坐标是Y,那么每一个X对应着都应该有一个相应的Y值,这就是我我们所说的每一个值。有一个值的映射可以对应在当前的纵坐标上啊,这就是函数的一个映射关系。一编程领域呢,我们也非常的熟悉,不管是哪一种语言里边都提供了类似函数这样的一种调用方法啊,我们知道在C语言或者Java语言里面,Java里面当然是一般啊,我们对于对象来讲,它是叫方法啊,那对于其他的一些语言,一般都是把它叫做函数,所谓的函数呢,其实就是包装起来的一系列操作,只不过这个操作呢,有可能我们可以加上一系列的传入参数,然后当前的。
01:15
这个函数经过把这些传入的参数做一些转换计算之后,还可以再返回一个计算得到的结果,那我们就把这个东西叫做函数,那看起来也是传入的这些东西不就相当于自变量X吗?返回的值不就相当于因变量Y吗?所以也是借鉴了数学上基本的函数的定义。当然了,有一些所谓的函数式编程语言,它对这个函数的要求,声明的要求就会更高一些,它就是完全意义上对应着数学上的这个函数表达是一种映射关系。而我们知道,在更广泛的编程语言里边,我们当前这个返回值可以是没有的啊,输入参数也可以没有,也就是说我可以构建一个无参的函数,也可以构建一个没有返回值的函数。所以有时候在我们的编程语言里边呢,这个函数它可能就不是简简单单的只指代一个映射关系了,有时候我们可能就是把一系列的操作包装起来。
02:19
然后最后返回或者不返回一个值就可以了,所以我们相当于把这个是包装起来的一组操作,所以有一些计算机科学家也是对这个定义会有更深入的讨论,他会说这个严格意义上来讲不叫函数,这个应该叫过程procedure啊,就是相当于是我们计算机执行一段代码的一个一个子集,一个过程,一个子过程啊,我们这里呢,就不做更多的区分,在CQ里边我们知道往就是把一系列操作包装起来,然后嵌入到CQ用里去统一查询统一就可。那这就相当于是我们可以直接调用的,已经帮我们包装好的一系列操作。
03:04
同样在flink里边,Table API和flinkq呢,同样提供了这个函数的功能,那这两种API在调用函数的时候是不一样的,因为我们知道table API本身是内嵌在Java语言里边的一种DSL嘛,一种这个高级的嵌入式的语言嘛,所以我们其实就是通过创建一个数据对象,然后点。来一个方法调用,实现这样的一个函数功能,而CQ里边呢,那就跟我们传统的标准CQ用法一样了,直接提供一个对应的函数名称,我们用的时候接拿它来调用就可以了,有可能有需要它有参数啊,那我们就传入对应的数据字段,那如果没有的话,直接调用就完事。比如说我们如果想要把一个字符串啊str转换成全大写的话,这个是非常熟悉的一个L当中的函数了,那table table API的写法是当前有这个S,它是一个string类型的对象,我们直接它的per case方法就可以把它转换成一个大写。
04:12
而CQ当中呢,CQ当中是把当前的这个SDR作为一个字段传给upper这样一个函数,所以我们用的时候就直接upper,然后里边的参数是SR,这样的话表示就是把当前这个字段转换成大写之后再去使用的这样的一个结果。那所以我们知道table API它是内嵌在Java语言里边嘛,所以如果说我们想要扩展当前table API里边的某一些函数功能的话,那很显然是需要在类里边做添加的,不停的要更改这个类里边的方法,所以它的扩展是比较麻烦的,目前table API支持的数是远远少于CQ当中的。啊,那我们在实际应用当中,肯定也是直接使用CQ的场景会更多,所以接下来呢,我们主要就是介绍flink CQ里的一些使用。
05:08
那flink CQ里边的函数呢,又整体来讲可以分成两大类,一大类就是所谓的CQ当中的内置系统函数,直接调用函数名,我们直接就对应的这个函数名就表示了一系列的功能啊,比如说之前我们就用过的count计数啊,聚合统计,诶,比如说这个chars,很明显这就是统计一个字符串长度嘛,或者前面我们看到这个upper转换成大写字母。根据它的这个方法,名名直观的可以看出它的功能,我们要用的时候直接调用就好了,这是系统link底层已经帮我们实现了的,我们可以直接拿来用。而另外一类呢,那就是系统没有帮我们实现的,我们如果想要用的话,那就自定义,这就是所谓的udf去创建一个自定义的函数。当然了,这个创建出来之后,我们应该是在代码当中先创建一个对应的类,然后把它的对象同样是要在表环境里边进行注册,才能在CPU当中去使用。就像之前我们对于表的那种应用一样,假如我们先得到了一个table类型的对象的话,也要在表环境里边进行注册,然后才可以使用。
06:21
那么接下来我们就对这两类函数分别进行介绍,首先我们要介绍的就是Li CQ当中的系统函数啊,那系统函数这一部分其实比较简单,就是它有一定的功能。另底层已经帮我们实现了,那我们就只要知道它是用来干嘛的,想要使用的时候,就像我们调一个函数一样啊。给他传参,然后直接调用就可以了啊,所以这种函数也叫做内置函数,以这是系统已经预先。实现给我们实现了的功能模块啊,那fliq目前已经提供了非常多的大量的系统函数,几乎已经支持了所有标准CQ里边的操作啊,所以直接调用系统函数为我们。
07:09
实际在做应用开发的时候提供了非常大的方便啊,这也是为什么现在越来越多的公司在做项目的时候会直接选用flink CQ的原因,因为它这里面的系统内置函数太强大了,我们很多如果你想在PI里面实现同样的功能的话,哎,那是可以实现,但是呢,有可能得我们自己去。做状态编程啊,自定义状态,甚至有可能要用到process啊,用底层的这个API去做实现非常的麻烦,定呢,直接一个函数调用就搞定了。这也是。作为高级应用层级的API给我们提供的最大的功能,那呃,这一部分呢,其实就是功能比较强大,但是其实应用或者说原理是非常简单的,我们简单的来分类,来考察了解一下FRAMEC9当中的系统函数啊呃,又可以分成两大类啊,那主要就是标量函数和聚合函数。
08:07
那所谓的标量函数标量在物理上我们知道有标量有矢量啊,那矢量的话,那就是有数值还有方向,比方说我们说这个力是一个矢量啊,这是有有大小有方向的这样的一个一个量物理量,而标量呢,就是只有数值没有方向。也就是说不带单位这样的一个量就是所谓的标量,那标量函数呢?简单意义上来讲,那就是只要指定对应的输入数据,然后我们直接把它做转换计算得到一个值返回就完事了,所以简单看的话有点像ma啊,那就是传入一个或多个字段,经过转换之后得到唯一的值,那另外呢,还有一些可能我们不需要有有对应的输入参数啊,直接调用之后返回唯一的值,这种函数也也属于标量函数。
09:03
这这这种函数,这其实是最为简单的一类系统函数啊,数量也是最为庞大的。在标准CQ里边其实有很多类似的定义啊,这个数量非常的杂,所以在这里我们就不做介绍了,如果兴的话,我们可以在用到的时候到官网上去做一个详细的了解,去对应的去做查询就可以了,这里边只是举一些比较常见的类型,然后呢,枚举出一些,呃。具有代表性的函数操作,简单的了解一下就可以了啊,那首先在这一类里边,比较函数是一种典型的标量函数,比较函数所谓的比较,那就是给一个比较表达式,用来判断两个值之间的关系,那它有没有返回值呢?有,它的返回值就是一个布尔类型了,所以最经典的当然就是大于小于等于判断它两者之间的关系。在CQ里边跟我们在Java语法里边不同啊,Java语法里边是两个等,双等,因为单单个的一个等号表示负值,CQ里面不存在,CQ里就直接等号判断两个值是否相等。
10:12
那如果判断两个值大于小于这个比较简单,那如果判断两个值不等怎么办呢?诶不等式直接用小于大于这种方式啊,表示这两个值是不等的,或者小于或者大于。那另外还有一个比较常见的判断值的这样一个比较函数呢,就是is not,我们看在CQ里面,它的特点就是有时候是以函数形式出现的,有时候呢,直接就像是。一系列关键字组合起来的一句话一样啊,就是is not now,那就是判断当前这个值是否不为空,如果当前值不为空的话,它返回处,如果为空就返回false。这个非常简单。然后接下来除了比较函数之外,还有一类我们也非常的熟悉,那就是逻辑函数,逻辑函数的话,那就是一个逻辑表达式了,前面比较函数可以认为就是一个逻辑表达式,因为它返回一个布尔类型值嘛。
11:08
而逻辑表达式呢,那就是多个这样的一个返回波尔类型的值,在用逻辑连接词把它们连接起来啊,那这就是所谓的与或非了,在CQ里边就是and or和not啊,当然了也可以用判断语句,就是is或者is not,像前面这个,其实本质上来讲,我们应该算一个逻辑函数啊,啊,那我们看常用的这种方法,那就是一个布尔类型的值,然后or另外一个,那当然就是取逻辑或了啊,那如果要是and的话,就是取逻辑语。Is false,那其实判断当前这个值是否为false,那其实就是它如果本身是false的话,这个返回就是true,如果本身为true的话,诶当前返回就是false,这有点像类似于一个逻辑非啊,那那下面这个not,然后加上波尔类型的表达值的话,这是标准的逻辑的一个取法。
12:04
啊,那这两者有什么区别呢?针对当前的传入进来这个布尔类型的值,我们知道在CQ里面有可能是unknown类型啊,就是不知道当前这个到底是什么,类似于我们的nu类型啊,那如果说本身当前类型是unknown的话,判断is false的时候,它也会直接返回false,就是只要它不是false,那就全部都是false。而对于直接的逻辑非而言呢,本身如果是unknown类型去逻辑非还是返回unknown,这个我们要稍微的区别一下。然后另外还有一个非常简单也是常见的就是算术函数了,算术函数非常简单,加减乘除,还有一些比较复杂的数学运算都包含在这一部分里边啊,那最简单的啊,两个值相加,那就直接用加号连接就可以了。这个跟我们平常在。语言编程语言里面的用法都是完全一样的,最为简单的啊,那比方说如果要是想做一个幂计算的话,我们可以调用power函数,标准的幂运算函数啊,我们就是求当前第一个数的第二个数次方来用POWER2函数。
13:16
那另外还有一个比较特殊的就是red没有任何的参数。它相当于我们在。编程语言里边调用的random函数,它返回的是0.0~1.0区间内的一个double类型的伪随机数,伪随机数啊,这是一个随机生成的一个数字。除了前面我们讲到的这些比较简单比较基本的标量函数之外啊,另外还有两类比较常见的标量函数,那一个就是字符串函数,字符字符串函数当然就是对字符串进行各种处理转换的函数了啊,最简单的比如说两个字符串连接,我们这个时候用的是双竖线,类似于逻辑表达式里边Java里边的。
14:02
逻辑获的那个表达啊,这里边我们是表示两个字符串的连接啊,那像前面我们还提到了upper传入一个字符串,那就是表示把这个字符串要转换为全大写的形式啊,那另外还有这个chars,这里是下划线,它是完整的一个函数名,里边传递一个字符串string,那么得到的就是这个字符串的长度。这是常规的一些比较常见的字符串函数,当然标准CQ里边,包括CQ里边实现了更多更为复杂的操作,我们可以参考官网里面的介绍啊。另外呢,还有一类比较特殊的就是间相关的函数,因为我们知道在流处理里边,时间是非常重要的一个特性啊。那对于时间有哪些基本操作呢?比如说这里边我们可以直接调用date,然后加一个string。好,这样的话,我们会以格式YYYY-MM-DD,也就是年月日这样的一个格式去解析字符串string,把它转换成一个CQ date类型Q里面的日期类型。
15:10
这是最常见的一种转换q date类型的方式啊,当然了,我们也可以把它转换成一个Q的time类型,戳类型啊,那同样也是后面加一个string,注意这个string格式默认是YYYY-MM-DD后面空格,然后HS,也就是说这是年月日十分秒的格式。后面可选择可以加一个毫秒这样的一个参数,转换过来就是一个CQ的时间戳了。另外呢,我们还可以什么东西都不加,什么东西都不写,不传入参数,直接一个。就可以直接返回本地时区的当前时间啊,它的类型呢,就是Co time啊,有时候我们可能不用这个current time,有时候直接调的是local。这两其实是完全。
16:01
另外还有一个非常常见的用法,这里就是前面我们都已经非常熟悉的关键。Inter后面要加两个参数,一个是一个string,这个string呢是一般是引起来的一个数字,然后在后面是一个string,是当前的一个单位啊,那这个呢,可以是单独的单位,比如说我们习习惯熟悉的second minute day hour这些都可以,另外呢,也可以是一段范围。啊,因为这个本身就是。范围间隔这样的一个含义吗?所以它也可以直接写成two hour哎这样的单位,或者是year month这样这样的符合单位。这是什么意思呢?比如说我们这里的有一个例子就是in,然后二杠十,Year two months啊,那表示的其实就是前边这个是年的个数,后边这个是月份的个数,那所以这个表示的就是两年010个月啊,所以这样的话,我们就可以不需要把它完全转换成比方说34个月啊,这样看起来非常复杂的一种表示,可以以我们更加熟悉的日常生活中的习惯来进行一个时间段的表达。
17:20
这就是关于标量函数的各种类型,在实际应用的过程当中,直接拿来调用就可以了。当然了,除了标量函数之外,另外还有一大类函数,就是我们之前已经反复提到过的聚合函数。聚合函数呢?跟标量函数不同,如果说标量函数类似于ma,那它就是把一个或者多个字段直接转换成唯一的值输出的话,那么我们这里的聚合函数呢?它是把表里边的多行值作为输入,然后提取字段进行聚合操作,得到一个唯一的聚合值,跟前面的这一个。标量函数所不同的是,标量函数即使这里边传入多个参数,我们会发现。
18:06
呃,比如说这里边啊,我们有两个string,或者说我们,呃,像这个取命运,命运算的时候要传入两个数字,注意这里边的两个数其实在CQ里边都是针对。表里边的某一行数据而言的,而当前这一行里边我们可能要提取两个字段,然后把它传进来啊,当然当前传进来参数也有可能是从某个字段经过转换之后得来的啊,反正它这两个值都是来源于同一行数据。而对于。聚合函数而言呢,诶,它就是传入的是多行数据了,当然这多行数据那就看我们怎么选取了,我们可以是直接先指定一个K,按照当前K去做分组,然后把这一组数据的多行拿出来进行聚合,那这就是我们所说的分组聚合。
19:01
啊,那另外呢,我们也可以是指定了K之后,然后再去开窗口,在当前window范围内,对当前每一个K的所有数据,多行数据组合起来,然后进行聚合计算,那就这就是我们所说的窗口聚合。另外还有所谓的over聚合,哎,那就是针对当前表里面的某一行数据,它以上以下啊,那我们知道在当前flink流处理里边的以下没有办法啊,我们只有是以上截取很多行,然后做一个聚合处理。这相当于只是针对当前做聚合的哪些行进行聚合,就是这个聚合的范围不同,它的共同特点其实都是多对一,得到了一个聚合之后的唯一值啊,那所以当前的这种聚合操作就类似于我们之前在datapi里边的啊,或者aggregate这样的一个操作。标准CQ里边,我们知道所有的这些聚合操作,不管在分组聚合里边啊,还是开窗聚合里边,还是FCQ里边,我们特定的这个特殊的啊,基于时间的窗口聚合也好,都可以调用相同的聚合函数,因为它底层机制都是一样的嘛,都是把多行聚合成一个值啊,那所以标准CQ里边常见聚合函数CQ都是支持的,而且在不断的扩展当中啊。
20:27
这在我们。具体的项目应用当中也是非常的常见,这里可以举一些常见例子啊,比如说count啊,那count芯这就是表示返回所有行的数量,直接统计一个个数,前面我们做这个PV或者统计个数的时候经常用到它。另外还可以sum,那sum的话就是对某个字段进行一个求和,默认情况下呢,我们可以省略关键字or对所有行进行求和,那如果指定了distinct的这样一个关键字的话,还可以对数据进行去重,这样的话每个值就只叠加一次了,相当于我们把这个呃去重的操作啊,直接利用distinct的关键字可以方便的进行处理。
21:11
另外还有两个比较特别的rank和number啊,那我们知道rank的话指的是当前值的排名,当前这一行的排名,而number呢,一般我们就是经过排序之后返回当前的行号,所以它的功能跟rank是类似的。所以我们知道这两个到底它用在哪里呢?前面讲到过,在top n这样一个需求当中,目前。Fliq是没有直接实现topn的函数的啊,它就需要使用over窗口进行一个聚合,提炼出当前的row number来,然后进行一个套喷的截取啊,那所以这个rank和row number一般是用在over窗窗口当中,在套当中有比较重要的作用。
22:02
这就是我们平常常见的系统函数包含的。标量函数和聚合函数。
我来说两句