Flink示例

本文介绍了如何使用ApacheFlinkSQL处理订单流数据,包括将DataStream转换为Table,创建视图,以及执行分组统计、TopN分析和批环境下的聚合查询。同时展示了如何在Scala和Java中使用TableAPI进行操作。
摘要由CSDN通过智能技术生成

Flink SQL

简单订单统计

假设有以下两个订单流数据,数据字段分别为用户ID、购买的商品名称、商品数量。

数据流A:

1L,"尺子",3

1L,"铅笔",4

3L,"橡皮",2

数据流B:

2L,"手表",3

2L,"笔记本",3

4L,"计算器",1

目标:合并两个流的数据,并筛选出商品数量大于2的订单数据。

import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.{$,EnvironmentSettings}
import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment
import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api_

/**
* Flink SQL统计订单流数据
* 知识点:DataStream转为Table、视图,Table转为DataStream
*/
object FlinkSQLDemo{
    def main(args:Array[String]):Unit={
        //创建流执行环境
        val env=StreamExecutionEnvironment.getExecutionEnvironment
        //创建EnvironmentSettings实例并设置参数
        val settings=EnvironmentSettings
            .newInstance() //创建一个用于创建EnvironmentSettings实例的构建器
            .useBlinkPlanner() //将Blink计划器设置为所需的模块(默认)
            .inStreamingMode() //设置组件以流模式工作,默认启用
            .build() //创建一个不可变的EnvironmentSettings实例

        //构建流式表执行环境StreamTableEnvironment
        val tableEnv: StreamTableEnvironment=StreamTableEnvironment.create(env,settings)

        //构建订单数据流A
        val orderStreamA:DataStream[Order]=env.fromCollection(
            List(Order(1L,"尺子",3),
                Order(1L,"铅笔",4),
                Order(3L,"橡皮",2)
            )
        )

        //构建订单数据流B
        val orderStreamA:DataStream[Order]=env.fromCollection(
            List(Order(2L,"手表",3),
                Order(2L,"笔记本",3),
                Order(4L,"计算器",1)
            )
        )

        //将DataStream转为Table,并指定Table的所有字段
        val tableA: Table=tableEnv.fromDataStream(orderStreamA,$"user",$"product",$"amount")

        //将Table的schema以摘要格式打印到控制台
        tableA.printSchema()
        //(
        // 'user' BIGINT,
        // 'product' STRING,
        // 'user' INT,
        //)
        //将DataStream转为视图,视图名称为tableB,并指定视图的所有字段
        tableEnv.createTemporaryView("tableB",orderStreamB,$("user"),$("product"),$("amount"))

        //执行SQL查询,合并查询结果
        println("tableA默认表名:"+tableA.toString)
        val resultTable:Table=tableEnv.sqlQuery(
            "SELECT * FROM " + tableA + " WHERE amount>2" +
            "UNION ALL "+
            "SELECT * FROM tableB WHERE amount > 2"
        )

        //将结果Table转为仅追加流
        val dataStreamResult=tableEnv.toAppendStream[Order](resultTable)
        //将流打印到控制台
        dataStreamResult.print()
        //触发程序执行
        env.execute()
    }
}

//创建订单样例
case class Order(user:Long,product:String,amount:Int)

在IDEA本地执行上述代码,控制台输出结果如下:

1> Order(1,铅笔,4)

11> Order(2,笔记本,3)

10> Order(2,手表,3)

12> Order(1,尺子,3)

计算产品类别销售额TopN

假设有一个存储产品类别销售额数据的文件sales.csv。

字段分别为日期、产品类别、销售额。

使用Flink SQL统计每一个产品类别销售额的前三名(分组求TopN)

在Maven项目中的pom.xml中添加支持读取CSV文件的Flink依赖:http://t.csdnimg.cn/bWIBB

Table API

Table API适用于Scala, Java和Python。

  • Scala Table API利用了Scala表达式
  • Java Table API既支持表达式DSL,也支持解析和转换为等效表达式的字符串
  • Python Table API目前只支持解析和转换为等效表达式的字符串

Table API聚合查询代码示例:

//获得表环境TableEnvironment
val tableEnv: TableEnvironment=...

//注册一个Order表

//扫描(读取)已注册的Orders表,返回结果Table(相当于将已注册的表转为Table,便于后续操作)
val orders: Table=tableEnv.from("Orders")
//计算来自法国的所有客户的收入
val revenue:Table=Orders
    .filter($"cCountry"==="FRANCE")
    .groupby($"cID",$"cName")
    .select($"cID",$"cName",$"revenue".sum AS "revSum")

    //Table转DataStream
    //执行查询

其中,读表语句val orders: Table=tableEnv.from("Orders")需注意:

从默认的Catalog和数据库中读取名称为tableName的表(或视图)
Table tab=tableEnv.from("tableName")
从指定的Catalog中读取名称为tableName的表
Table tab=tableEnv.from("catalogName.dbName.tableName")
使用转义从指定的Catalog中读取表(例如,数据库名称中的点必须转义)
Table tab=tableEnv.from("catalogName.`db.Name`.tableName")

订单分组计数

假设有一个名为Orders的已注册表具有属性a,b,c,rowtime。

下面分别使用Scala和Java Table API在批环境中对Order表进行处理。

扫描Orders表,按照字段a分组,并计算每组的数据行数。

Java Table API
// Java Table API需要导出的包
import org.apache.flink.table.api.*;
// 对于表达式DSL,需要导入静态包
import static org.apache.flink.table.api.Expressions.*;

// 环境配置
EnvironmentSettings settings=EnvironmentSettings
    .newInstance()
    .inStreamingMode()
    .build();
TableEnvironment tEnv=TableEnvironment.create(settings);

// 向表环境注册一个Orders表
// ...

// 读取已注册的Orders表,返回结果Table(相当于将已注册的表转化为Table,便于后续操作)
Table orders=tEnv.from("Orders"); //字段:(a,b,c,rowtime)
//查询表
Table counts=orders
    .groupBy($("a")) //按照a分组
    .select($("a"),$("b").count().as("cnt"));

//将结果Table转为DataSet
DataSet<Row> result=tEnv.toDataSet(counts,Row.class);
result.print();
Scala Table API
import org.apache.flink.api.scala._
import org.apache.flink.table.scala._
import org.apache.flink.table.api.bridge.scala._

//环境配置
val settings=EnvironmentSettings
    .newInstance()
    .inStreamingMode()
    .build();
val tEnv=TableEnvironment.create(settings);

//注册Orders表
//...

//读取已注册的Orders表,返回结果Table(相当于将已经注册的表转为Table,便于后续操作)
val orders=tEnv.from("Orders") //字段:(a,b,c,rowtime)
//查询并打印结果
val result=orders
          .groupBy($"a") //按照a分组
          .select($"a",$"b".count as "cnt")
          .toDataSet[Row] //转为DataSet
          .print()

每小时订单分组求平均值

扫描Orders表,过滤空值,并按照字段a分组,每小时计算一次各组数据中字段b的平均值。

Java Table API
//读取表Orders
Table orders=tEnv.from("Orders"); //字段:(a,b,c,rowtime)
//执行查询
Table result=orders
        //过滤空值
        .filter(
            and(
                $("a").isNotNull(),
                $("b").isNotNull(),
                $("c").isNotNull()
            ))
        //字段a转为小写
        .select($("a").lowerCase().as("a"),$("b"),$("rowtime"))
        //1小时滚动窗口
        .window(Tumble.over(lit(1).hours()).on($("rowtime")).as("hourlyWindow"))
        //按照窗口和字段a分组
        .groupBy($("hourlyWindow"),$("a"))
        //查询字段a,窗口结束时间,字段b平均值
        .select($("a"),$("hourlyWindow").end().as("hour"),$("b").avg().as("avgBillingAmount"));
Scala Table API
//读取Orders表
val orders:Table=tEnv.from("Orders") //字段:(a,b,c,rowtime)
//执行查询
val result:Table=orders
        //过滤空值
        .filter($"a".isNotNull && $"b".isNotNull && $"c".isNotNull)
        //字段a转为小写
        .select($"a".lowerCase() as "a",$"b",$"rowtime")
        //1小时滚动窗口
        .window(Tumble over 1.hour on $"rowtime" as "hourlyWindow")
        //按照窗口,字段a分组
        .groupBy($"hourlyWindow",$"a")
        //查询字段a,窗口结束时间,字段b的平均值
        .select($"a",$"hourlyWindow".end as "hour",$"b".avg as "avgBillingAmount")
            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值