Flink Stream Batch Integrated Computing (14): SQL-Abfrage der PyFlink Tabel API

Zum Beispiel

Fragen Sie die Quelltabelle ab und führen Sie gleichzeitig Berechnungen durch

# 通过 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)

Tabellen-API-Abfrage

Das Table-Objekt verfügt über viele Methoden, mit denen relationale Operationen ausgeführt werden können.

Diese Methoden geben neue Tabellenobjekte zurück, die die Ergebnisse der Anwendung relationaler Operationen auf die Eingabetabelle darstellen.

Diese relationalen Operationen können aus mehreren Methodenaufrufen bestehen, beispielsweise table.group_by(...).select(...).

In der Table-API-Dokumentation werden alle unterstützten Table-API-Vorgänge für Streams und Batches beschrieben.

Das folgende Beispiel zeigt eine einfache Tabellen-API-Aggregationsabfrage:

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()

Die Tabellen-API unterstützt auch die Zeilenoperations-API. Zu diesen Zeilenoperationen gehören Kartenoperation, FlatMap-Operation, Aggregate-Operation und FlatAggregate-Operation.

Das folgende Beispiel zeigt eine einfache zeilenbasierte Tabellen-API-Abfrage

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-Abfrage

Flinks SQL basiert auf Apache Calcite, das Standard-SQL implementiert. SQL-Abfrageanweisungen werden mithilfe von Zeichenfolgen ausgedrückt. SQL unterstützt die Konvektions- und Stapelverarbeitung von Flink.

Das folgende Beispiel zeigt eine einfache SQL-Aggregationsabfrage:

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()

Mischtabellen-API und SQL

Das Tabellenobjekt in der Tabellen-API und die Tabelle in SQL können frei ineinander konvertiert werden.

Das folgende Beispiel zeigt, wie das Table-Objekt in SQL verwendet wird:

create_temporary_view(view_path, table) Registrieren Sie ein „Table“-Objekt als temporäre Tabelle, ähnlich der temporären SQL-Tabelle.

# 创建一张 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()

Das folgende Beispiel zeigt, wie SQL-Tabellen in der Tabellen-API verwendet werden:

sql_query(query) Führt eine SQL-Abfrage aus und gibt das Ergebnis der Abfrage als „Tabellen“-Objekt zurück.

# 创建一张 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()

Optimierung

Datenverzerrung

Wenn die Daten verzerrt sind (ein bestimmter Teil der Daten ist besonders groß), obwohl kein GC ( Gabage Collection , Garbage Collection) vorhanden ist, ist die Ausführungszeit der Aufgabe ernsthaft inkonsistent.

  • Der Schlüssel muss neu gestaltet werden, um die Aufgabengröße mit einem Schlüssel mit kleinerer Granularität zu rationalisieren.
  • Ändern Sie den Grad der Parallelität.
  • Rufen Sie den Neuausgleichsvorgang auf, um die Datenpartition gleichmäßig zu machen.

Puffer-Timeout-Einstellung

Da während der Aufgabenausführung Daten über das Netzwerk ausgetauscht werden , kann der Puffer-Timeout-Zeitraum für die Datenübertragung zwischen verschiedenen Servern über setBufferTimeout festgelegt werden .

Wenn „setBufferTimeout(-1)“ festgelegt ist , wird vor der Aktualisierung darauf gewartet, dass der Puffer voll ist, sodass der maximale Durchsatz erreicht werden kann. Wenn „setBufferTimeout(0)“ festgelegt ist , kann die Verzögerung minimiert werden Daten werden aktualisiert, sobald sie empfangen werden. Wenn „setBufferTimeout“ auf größer als 0 eingestellt wird , wird der Puffer nach dieser Zeit abgelaufen und dann wird der Puffer aktualisiert.

Beispiele können sich auf Folgendes beziehen:

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

Guess you like

Origin blog.csdn.net/victory0508/article/details/132358265