Flink 1.9 Table API & SQL 1

Flink 1.9 Table API & SQL

​ Apache Flink具有两个关系API-Table API和SQL-用于统一流和批处理。Table API是用于Scala和Java的语言集成查询API,它允许以非常直观的方式例如使用关系运算符(选择,过滤和联接等)来进行查询。Flink的SQL基于标准的Apache Calcite。无论输入是批处理输入(DataSet)还是流输入(DataStream),在两个接口中指定的查询都具有相同的语义并指定相同的结果。

程序依赖

根据目标编程语言,您需要将Java或Scala API添加到项目中,以便使用Table API和SQL定义管道:



  org.apache.flink
  flink-table-api-java-bridge_2.11
  1.9.0
  provided



  org.apache.flink
  flink-table-api-scala-bridge_2.11
  1.9.0
  provided

此外,如果要在IDE中本地运行Table API和SQL程序,则必须添加以下一组模块之一,具体取决于要使用的计划程序:



  org.apache.flink
  flink-table-planner_2.11
  1.9.0
  provided



  org.apache.flink
  flink-table-planner-blink_2.11
  1.9.0
  provided

在内部,表生态系统的一部分在Scala中实现。因此,请确保为批处理和流应用程序都添加以下依赖项:


  org.apache.flink
  flink-streaming-scala_2.11
  1.9.0
  provided

扩展依赖

如果要实现与Kafka或一组用户定义的函数进行交互的自定义格式,则以下依赖关系就足够了,并且可以用于SQL Client的JAR文件:


  org.apache.flink
  flink-table-common
  1.9.0
  provided

当前,该模块包括以下扩展点:

  • SerializationSchemaFactory

  • DeserializationSchemaFactory

  • ScalarFunction

  • TableFunction

  • AggregateFunction

Table API和SQL程序的通用结构

// create a TableEnvironment for specific planner batch or streaming
// **********************
// 使用原Flink的Planner进行流式处理
// **********************
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.EnvironmentSettings
import org.apache.flink.table.api.scala.StreamTableEnvironment

val fsSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val fsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val fsTableEnv = StreamTableEnvironment.create(fsEnv, fsSettings)
// or val fsTableEnv = TableEnvironment.create(fsSettings)

// ******************
// 使用原Flink的Planner进行批式处理
// ******************
import org.apache.flink.api.scala.ExecutionEnvironment
import org.apache.flink.table.api.scala.BatchTableEnvironment

val fbEnv = ExecutionEnvironment.getExecutionEnvironment
val fbTableEnv = BatchTableEnvironment.create(fbEnv)

// **********************
// 使用BLINK的Planner进行流式处理
// **********************
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.EnvironmentSettings
import org.apache.flink.table.api.scala.StreamTableEnvironment

val bsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val bsSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build()
val bsTableEnv = StreamTableEnvironment.create(bsEnv, bsSettings)
// or val bsTableEnv = TableEnvironment.create(bsSettings)

// ******************
// 使用BLINK的Plan批ner进行流式处理
// ******************
import org.apache.flink.table.api.{EnvironmentSettings, TableEnvironment}

val bbSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inBatchMode().build()
val bbTableEnv = TableEnvironment.create(bbSettings)
//以上为创建一个TableEnvironment的几种不同的场景

// register a Table
tableEnv.registerTable("table1", ...)           // or
tableEnv.registerTableSource("table2", ...)     // or
tableEnv.registerExternalCatalog("extCat", ...)

// register an output Table
tableEnv.registerTableSink("outputTable", ...);

// create a Table from a Table API query
val tapiResult = tableEnv.scan("table1").select(...)

// create a Table from a SQL query
val sqlResult  = tableEnv.sqlQuery("SELECT ... FROM table2 ...")

// emit a Table API result Table to a TableSink, same for SQL result
tapiResult.insertInto("outputTable")

// execute
tableEnv.execute("scala_job")

###Table API对列的操作

//执行字段添加操作。如果添加的字段已经存在,它将引发异常
val orders = tableEnv.scan("Orders");
val result = orders.addColumns(concat('c, "Sunny"))
//如果添加列名称与现有列名称相同,则现有字段将被替换
val result = orders.addOrReplaceColumns(concat('c, "Sunny") as 'desc)

//执行字段删除操作。字段表达式应该是字段引用表达式,并且只能删除现有字段。
val orders = tableEnv.scan("Orders")
val result = orders.dropColumns('b, 'c)

//执行字段重命名操作。字段表达式应该是别名表达式,并且只有现有字段可以重命名。
val orders = tableEnv.scan("Orders");
val result = orders.renameColumns('b as 'b2, 'c as 'c2)

查询小案例

import org.apache.flink.table.api.scala._
import org.apache.flink.api.scala._
//Table API使用Scala隐式。确保导入以上隐式进行隐式转换

// register Orders table  
tableEnv.registerTable("Orders", Orders)

// ******************
//1.使用Table API进行表的查询
// ******************

val orders = tableEnv.scan("Orders")
// compute revenue for all customers from France
//以单个记号(')开头来引用表的属性
val revenue = orders
  .filter('cCountry === "France")                 //筛选
  .groupBy('cID, 'cName)                          //分组        
  .select('cID, 'cName, 'revenue.sum AS 'revSum)  //查询计算

// ******************
//2.使用SQL进行表的查询
// ******************
val revenue = tableEnv.sqlQuery(
  """
  |SELECT cID, cName, SUM(revenue) AS revSum
  |FROM Orders
  |WHERE cCountry = 'FRANCE'
  |GROUP BY cID, cName
  """
  .stripMargin) //stripMargin 删除由空格或控制字符组成的前导前缀

Flink SQL Row 类型使用

row 字段 整体可以理解为一个map key为字段的名称,value为字段的类型

使用场景之一:

使用flink Sql 去读取kafka中的json格式 ,json数据中再次嵌套数据时使用

{
    "market_id":"108",
    "info":{
        "market_name":"北京商城",
        "area":"北京"
    }
}

针对上面json格式Flink Sql DDl中定义语句:

market_id int,
info Row

**注意:**Flink SQL中如果想要使用关键字作为字段名称,需要用反引号( ``)引起来

​ Flink SQL 中定义HBase维表时,具体使用的字段的数据类型要和 HBase 表具体存储的字段类型保持一致

​ Flink SQL 不支持short类型或者其它自定义类型

TOPN计算

目前,Blink仅支持ROW_NUMBER作为窗口功能。

val env = StreamExecutionEnvironment.getExecutionEnvironment
val tableEnv = TableEnvironment.getTableEnvironment(env)

// read a DataStream from an external source
val ds: DataStream[(String, String, String, Long)] = env.addSource(...)
// register the DataStream under the name "ShopSales"
tableEnv.registerDataStream("ShopSales", ds, 'product_id, 'category, 'product_name, 'sales)

// select top-5 products per category which have the maximum sales.
val result1 = tableEnv.sqlQuery(
    """
      |SELECT product_id, category, product_name, sales  -- 优化 省略查询row_num字段
      |FROM (
      |   SELECT *,
      |       ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) as row_num
      |   FROM ShopSales)
      |WHERE row_num <= 5
    """
    .stripMargin)

为了将上述查询输出到外部存储并获得正确的结果,外部存储必须具有与Top-N查询相同的唯一键。在上面的示例查询中,如果product_id_是查询的唯一键,则外部表也应具有product_id作为唯一键。

窗口计算平均帐单

val orders: Table = tableEnv.scan("Orders")                     // schema (a, b, c, rowtime)
val result: Table = orders
        .filter('a.isNotNull && 'b.isNotNull && 'c.isNotNull)   //过滤空值
        .select('a.lowerCase() as 'a, 'b, 'rowtime)
        .window(Tumble over 1.hour on 'rowtime as 'hourlyWindow)//设定滚动窗口时间间隔1小时
        .groupBy('hourlyWindow, 'a)                             //分组
        .select('a, 'hourlyWindow.end as 'hour, 'b.avg as 'avgBillingAmount)
        //每个小时计算并产生a平均帐单金额b

你可能感兴趣的:(Flink,1.9,Table,API,&,SQL,hive)