Flink流批一体计算(14):PyFlink Tabel API之SQL查询

本文详细讲解了使用Flink的TableAPI进行关系操作、SQL聚合和行操作,以及如何处理数据倾斜和调整缓冲区设置以优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

举个例子

查询 source 表,同时执行计算

# 通过 Table API 创建一张表:
source_table = table_env.from_path("datagen")
# 或者通过 SQL 查询语句创建一张表:
source_table = table_env.sql_query("SELECT * FROM datagen")
result_table = source_table.select(source_table.id + 1, source_table.data)

Table API 查询

Table 对象有许多方法,可以用于进行关系操作。

这些方法返回新的 Table 对象,表示对输入 Table 应用关系操作之后的结果。

这些关系操作可以由多个方法调用组成,例如 table.group_by(...).select(...)。

Table API 文档描述了流和批处理上所有支持的 Table API 操作。

以下示例展示了一个简单的 Table API 聚合查询:

from pyflink.table import Environmentsettings, TableEnvironment
# 通过 batch table environment 来执行查询
env_settings = Environmentsettings.in_batch_mode()
table_env = TableEnvironment.create(env_settings)
orders = table_env.from_elements([('Jack', 'FRANCE', 10), ('Rose', 'ENGLAND', 30), ('Jack', 'FRANCE', 20)],['name', 'country', 'revenue'])
# 计算所有来自法国客户的收入
revenue = orders \
    .select(orders.name, orders.country, orders.revenue) \
    .where(orders.country == 'FRANCE') \
    .group_by(orders.name) \
    .select(orders.name, orders.revenue.sum.alias('rev_sum'))
revenue.to_pandas()

Table API 也支持行操作的 API, 这些行操作包括 Map Operation, FlatMap Operation, Aggregate Operation 和 FlatAggregate Operation.

以下示例展示了一个简单的 Table API 基于行操作的查询

from pyflink.table import Environmentsettings, TableEnvironment
from pyflink.table import DataTypes
from pyflink.table.udf import udf
import pandas as pd

# 通过 batch table environment 来执行查询
env_settings = Environmentsettings.in_batch_mode()
table_env = TableEnvironment.create(env_settings)
orders = table_env.from_elements([('Jack', 'FRANCE', 10), ('Rose', 'ENGLAND', 30), ('Jack', 'FRANCE', 20)], ['name', 'country', 'revenue'])
map_function = udf(lambda x: pd.concat([x.name, x.revenue * 10], axis=1),
    result_type=DataTypes.ROW(
        [DataTypes.FIELD("name", DataTypes.STRING()),
        DataTypes.FIELD("revenue", DataTypes.BIGINT())]),
    func_type="pandas")
orders.map(map_function).alias('name', 'revenue').to_pandas()

SQL 查询

Flink 的 SQL 基于 Apache Calcite,它实现了标准的 SQL。SQL 查询语句使用字符串来表达。SQL 支持Flink 对流和批处理。

下面示例展示了一个简单的 SQL 聚合查询:

from pyflink.table import Environmentsettings, TableEnvironment

# 通过 stream table environment 来执行查询

env_settings = Environmentsettings.in_streaming_mode()

table_env = TableEnvironment.create(env_settings)

table_env.execute_sql("""

    CREATE TABLE random_source (

        id BIGINT,

        data TINYINT

    ) WITH (

        'connector' = 'datagen',

        'fields.id.kind'='sequence',

        'fields.id.start'='1',

        'fields.id.end'='8',

        'fields.data.kind'='sequence',

        'fields.data.start'='4',

        'fields.data.end'='11'

    )

""")

table_env.execute_sql("""

    CREATE TABLE print_sink (

        id BIGINT,

        data_sum TINYINT

    ) WITH (

        'connector' = 'print'

    )

""")

table_env.execute_sql("""

    INSERT INTO print_sink

        SELECT id, sum(data) as data_sum FROM

            (SELECT id / 2 as id, data FROM random_source)

        WHERE id > 1

        GROUP BY id

""").wait()

Table API 和 SQL 的混合使用

Table API 中的 Table 对象和 SQL 中的 Table 可以自由地相互转换。

下面例子展示了如何在 SQL 中使用 Table 对象:

create_temporary_view(view_path, table)  将一个 `Table` 对象注册为一张临时表,类似于 SQL 的临时表。

# 创建一张 sink 表来接收结果数据
table_env.execute_sql("""
    CREATE TABLE table_sink (
        id BIGINT,
        data VARCHAR
    ) WITH (
        'connector' = 'print'
    )
""")
# 将 Table API 表转换成 SQL 中的视图
table = table_env.from_elements([(1, 'Hi'), (2, 'Hello')], ['id', 'data'])
table_env.create_temporary_view('table_api_table', table)
# 将 Table API 表的数据写入结果表
table_env.execute_sql("INSERT INTO table_sink SELECT * FROM table_api_table").wait()

下面例子展示了如何在 Table API 中使用 SQL 表:

sql_query(query)   执行一条 SQL 查询,并将查询的结果作为一个 `Table` 对象。

# 创建一张 SQL source 表
table_env.execute_sql("""
    CREATE TABLE sql_source (
        id BIGINT,
        data TINYINT
    ) WITH (
        'connector' = 'datagen',
        'fields.id.kind'='sequence',
        'fields.id.start'='1',
        'fields.id.end'='4',
        'fields.data.kind'='sequence',
        'fields.data.start'='4',
        'fields.data.end'='7'
    )
""")

# 将 SQL 表转换成 Table API 表
table = table_env.from_path("sql_source")
# 或者通过 SQL 查询语句创建表
table = table_env.sql_query("SELECT * FROM sql_source")
# 将表中的数据写出
table.to_pandas()

优化

数据倾斜

当数据发生倾斜(某一部分数据量特别大),虽然没有GCGabage Collection,垃圾回收),但是task执行时间严重不一致。

  • 需要重新设计key,以更小粒度的key使得task大小合理化。
  • 修改并行度。
  • 调用rebalance操作,使数据分区均匀。
缓冲区超时设置

由于task在执行过程中存在数据通过网络进行交换,数据在不同服务器之间传递的缓冲区超时时间可以通过setBufferTimeout进行设置。

当设置“setBufferTimeout(-1)”,会等待缓冲区满之后才会刷新,使其达到最大吞吐量;当设置“setBufferTimeout(0)”时,可以最小化延迟,数据一旦接收到就会刷新;当设置“setBufferTimeout”大于0时,缓冲区会在该时间之后超时,然后进行缓冲区的刷新。

示例可以参考如下:

env.setBufferTimeout(timeoutMillis);
env.generateSequence(1,10).map(new MyMapper()).setBufferTimeout(timeoutMillis);

Flink 批流一体编程实践可以通过 Table/SQL API 和 DataStream/DataSet API 两种方式来实现。下面将分别介绍这两种方式的实现方法。 1. Table/SQL API 实现批流一体编程实践 Table/SQL APIFlink 提供的一种基于 SQL 的编程接口,可以将流处理和批处理统一起来。通过 Table/SQL API,用户可以使用 SQL 语句来操作流和批数据,从而实现批流一体的编程。 下面是一个使用 Table/SQL API 实现批流一体编程的示例代码: ```python from pyflink.table import StreamTableEnvironment, BatchTableEnvironment, EnvironmentSettings # 创建流处理环境 stream_env = StreamExecutionEnvironment.get_execution_environment() stream_env.set_parallelism(1) stream_table_env = StreamTableEnvironment.create(stream_env) # 创建批处理环境 batch_env = ExecutionEnvironment.get_execution_environment() batch_env.set_parallelism(1) batch_table_env = BatchTableEnvironment.create(batch_env) # 创建表 stream_table_env.execute_sql("CREATE TABLE source_table (id INT, name STRING) WITH ('connector' = 'kafka', 'topic' = 'source_topic', 'properties.bootstrap.servers' = 'localhost:9092', 'format' = 'json')") batch_table_env.execute_sql("CREATE TABLE sink_table (id INT, name STRING) WITH ('connector' = 'jdbc', 'url' = 'jdbc:mysql://localhost:3306/test', 'table-name' = 'sink_table', 'username' = 'root', 'password' = '123456', 'driver' = 'com.mysql.jdbc.Driver')") # 执行查询 result_table = stream_table_env.sql_query("SELECT id, name FROM source_table WHERE id > 10") result_table.insert_into("sink_table") # 执行作业 stream_table_env.execute("job_name") ``` 在上面的示例代码中,我们首先创建了一个流处理环境和一个批处理环境,然后分别使用 StreamTableEnvironment 和 BatchTableEnvironment 创建了对应的表环境。接着,我们使用 execute_sql() 方法创建了一个输入表和一个输出表,并使用 sql_query() 方法执行了一个查询操作,最后使用 insert_into() 方法将查询结果插入到输出表中。最后,我们使用 execute() 方法执行了整个作业。 2. DataStream/DataSet API 实现批流一体编程实践 除了 Table/SQL APIFlink 还提供了 DataStream/DataSet API 来实现批流一体编程。通过 DataStream/DataSet API,用户可以使用相同的 API 来操作流和批数据,从而实现批流一体的编程。 下面是一个使用 DataStream/DataSet API 实现批流一体编程的示例代码: ```python from pyflink.common.serialization import SimpleStringSchema from pyflink.datastream import StreamExecutionEnvironment from pyflink.datastream.connectors import FlinkKafkaConsumer from pyflink.dataset import ExecutionEnvironment # 创建流处理环境 stream_env = StreamExecutionEnvironment.get_execution_environment() stream_env.set_parallelism(1) # 创建批处理环境 batch_env = ExecutionEnvironment.get_execution_environment() batch_env.set_parallelism(1) # 创建数据源 stream_source = FlinkKafkaConsumer('source_topic', SimpleStringSchema(), {'bootstrap.servers': 'localhost:9092'}) batch_source = batch_env.from_elements([(1, 'a'), (2, 'b'), (3, 'c')]) # 执行流处理 stream_env.add_source(stream_source).filter(lambda x: int(x.split(',')[0]) > 10).print() # 执行批处理 batch_source.filter(lambda x: x[0] > 1).print() # 执行作业 stream_env.execute('job_name') ``` 在上面的示例代码中,我们首先创建了一个流处理环境和一个批处理环境,然后分别使用 FlinkKafkaConsumer 和 from_elements() 方法创建了对应的数据源。接着,我们使用 filter() 方法对数据进行过滤,并使用 print() 方法输出结果。最后,我们使用 execute() 方法执行了整个作业。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值