pyFlink 入门总结

一 整体流程

1. 初始化pyFlink执行环境
2. 加载数据集
3. 执行数据分析
4. 导出分析结果
 
二 初始化执行环境

2.1 初始化

参考代码如下
from pyflink.table import EnvironmentSettings, StreamTableEnvironment
es = EnvironmentSettings.new_instance().in_batch_mode().build()
tv = StreamTableEnvironment.create(environment_settings=es)

2.2 其它

待补充其它初始化方法,如流处理等

三 加载数据集

3.1 基于变量

参考代码如下
data = [['T1', 34, 'XY'],['T2', 34, 'NY'],['T3', 33, 'XX'],['T4', 33, 'JZ'],['T5', 33, 'SZ'],['T6', 33, 'PDS'],['T7', 32, 'XC'],['T8', 32, 'NY']]
tbl = tv.from_elements(data, ['name','age','city'],['STRING','INT','STRING'])
tv.create_temporary_view('itable', tbl)  # 注册为flinksql能访问的对向

3.2 基于pandas.DataFrame

dfa = pd.DataFrame(data, columns='name age city'.split())
tbl = tv.from_pandas(dfa) 

3.3 基于csv

csv_path = 'iexample.csv'
csv_schema = 'name string, age int, city string'
csv_sql = F"create table iTable({csv_schema}) with ('connector' = 'filesystem', 'path' = '{csv_path}', 'format' = 'csv'))"
tv.execute_sql(csv_sql)
tbl = tv.from_path('iTable')
经验1 包含表头的csv会报错
经验2 csv_sql 后面的with 中的引号必须是 单引号 双引号会报错
经验3 不要创建重名的表,会报错 此条有待进一步确认
 

3.4 连接postgresql

from pyflink.table import EnvironmentSettings, StreamTableEnvironment
es = EnvironmentSettings.new_instance().in_batch_mode().build()
tv = StreamTableEnvironment.create(environment_settings=es)
 
pg_schema = 'name STRING, age INT, city string'
dsn = F'jdbc:postgresql://{host}:{port}/{database}'
pg_sql = F"create table pg_table ({pg_schema})with ('connector'='jdbc','url'='{dsn}','table-name'='{table_name}','driver'='org.postgresql.Driver','username'='{user}','password'='{pwd}')"
print(pg_sql)
tv.execute_sql(pg_sql)
tbl = tv.from_path('pg_table')
tbl.limit(5).execute().print()
经验4 需要下载flink-connector-jdbc-*.jar文件 和 postgresql-*.jar文件 对应目录是pyflink安装目录的 lib文件夹下
经验5 连接依赖文件与数据库版本也有关系

四 数据处理

4.1 简单处理

1) select

from pyflink.table.expressions import col, call
tt = tbl.select(col("city"))
tt.limit(3).execute().print()

2)group_by

tbl.group_by(col('city')).select(col('city'),call("count", col('city')).alias('cnt')).execute().print()
tv.register_table('itable', tbl)
tv.sql_query('select city, count(*)cnt from itable group by city').execute().print()

3)order_by

tbl.order_by(col('age').desc).execute().print()

4)buildin function

tbl.select(call('avg',col('age')).alias('age_avg')).execute().print()
tbl.select(call('sum',col('age')).alias('age_sum')).execute().print()

5)normalized


@udf(result_type='Row<_name string, _age float>', func_type='pandas')
def inormal(data: pd.DataFrame) -> pd.DataFrame:
    data['_age'] = (data['age']-data['age'].mean())/data['age'].std()
    return data[['name', '_age']]
tbl.map(inormal).execute().print()

6)map & udf


@udf(result_type='Row<_name string, province string>', func_type='pandas')
def itown(data: pd.DataFrame) -> pd.DataFrame:
    data['province'] = data.city.apply(lambda x: dct.get(x))
    return data[['name', 'province']]
tbl.map(itown).execute().print()

4.2 其它处理

待补充

五 输出

5.1 print

tbl.map(itown).execute().print()

5.2 CSV

# 定义输出 CSV 文件的 schema
sink_schema = "name STRING, age int, _age float, city string, province string"
# 定义输出 CSV 文件的目录
sink_path = "tmpfile"
# 注册输出表
tv.execute_sql(f"""
    CREATE TABLE sink_table (
        {sink_schema}
    ) WITH (
        'connector' = 'filesystem',
        'path' = '{sink_path}',
        'format' = 'csv'
    )
""")

_age = tbl.map(inormal)
_town = tbl.map(itown)
t1 = tbl.join(_age).where(col('name')==col('_name')).select(col('name'), col('age'), col('_age'), col('city'))
t2 = t1.join(_town).where(col('name')==col('_name')).select(col('name'), col('age'), col('_age'), col('city'), col('province'))
tv.create_temporary_view('jtable', t2)  # old api tv.register_table

# 执行查询并将结果写入输出表
sql = 'INSERT INTO sink_table(name, age, _age, city, province) SELECT name, age, _age, city, province FROM jtable'
tv.execute_sql(sql).wait()
 

经验6 csv输出路径只能指定目录 不能指定名称

经验7 数据库输出需要提前创建供写入的表

5.3 POSTGRESQL


pg_schema = "name STRING, age int, _age float, city string, province string"
dsn = F'jdbc:postgresql://{host}:{port}/{database}'
pg_sql = F"create table pg_table ({pg_schema})with ('connector'='jdbc','url'='{dsn}','table-name'='{table_name}','driver'='org.postgresql.Driver','username'='{user}','password'='{pwd}')"
tv.execute_sql(pg_sql)  # create

sql = 'INSERT INTO pg_table(name, age, _age, city, province) SELECT name, age, _age, city, province FROM jtable'
tv.execute_sql(sql).wait() 




posted @ 2024-05-13 10:14  ddzhen  阅读(300)  评论(0编辑  收藏  举报