1. TableEnvironment 是什么,解决什么问题
Flink 的 Table/SQL 是声明式 API,你写的 DDL、SQL、Table API 链式调用,本质上都是在描述"要什么",由 Flink Planner 生成执行计划并提交作业执行。
TableEnvironment 的职责可以理解为三件事:
- 定义与管理元数据:临时表/视图、Catalog 表/视图、函数、模块
- 构建与解释计划:sql_query/explain_sql、Table.explain、StatementSet.explain
- 触发执行与作业配置:execute_sql(DML)、StatementSet.execute、Table.execute_insert,配置并行度/容错等
2. 创建 TableEnvironment 的两种常用方式
2.1 推荐方式:EnvironmentSettings 创建(更纯粹的 Table/SQL 程序)
适用于:主要用 Table API / SQL,不强依赖 DataStream API。
python
from pyflink.common import Configuration
from pyflink.table import EnvironmentSettings, TableEnvironment
config = Configuration()
config.set_string('execution.buffer-timeout', '1 min')
env_settings = (
EnvironmentSettings.new_instance()
.in_streaming_mode()
.with_configuration(config)
.build()
)
table_env = TableEnvironment.create(env_settings)
要点:
in_streaming_mode()常用于流作业;你也可以按需要选择 batch 模式with_configuration(config)可以把一些执行参数提前塞进去(例如 buffer-timeout)
2.2 与 DataStream 互操作:StreamTableEnvironment(需要 DataStream 能力时)
适用于:你想在同一条链路里混用 DataStream 与 Table/SQL(例如自定义 Source、复杂 ProcessFunction、Table 负责聚合与 Join)。
python
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.table import StreamTableEnvironment
env = StreamExecutionEnvironment.get_execution_environment()
table_env = StreamTableEnvironment.create(env)
经验建议:
- 如果你不需要 DataStream 侧能力,就用纯 TableEnvironment,更简单
- 如果你要用 DataStream 的 source/sink 或算子,就用 StreamTableEnvironment
3. Table/SQL 操作:建表、视图、查询与执行(最常用 API)
这一组 API 就是日常"写作业"的主流程。
3.1 从 Python 数据构造 Table:from_elements / from_pandas
快速构造测试数据、单元测试、demo 都很好用。
from_elements(elements, schema=None, verify_schema=True)from_pandas(pdf, schema=None, split_num=1)
例子:
python
table = table_env.from_elements([(1, 'Hi'), (2, 'Hello')], ['id', 'data'])
3.2 取出已注册对象:from_path
from_path(path) 用来把 Catalog/临时对象转成 Table:
python
t = table_env.from_path("sql_source")
它也是替代旧 API scan() 的推荐写法。
3.3 注册与管理视图:create_temporary_view / create_view
create_temporary_view(view_path, table):临时视图(会话级)create_view(view_path, table, ignore_if_exists=False):持久视图(取决于 Catalog 是否持久化)
典型用法:把 Table API 产物暴露给 SQL 使用。
python
table_env.create_temporary_view("table_api_table", table)
table_env.execute_sql("INSERT INTO sink SELECT * FROM table_api_table")
3.4 注册与管理表:create_temporary_table / create_table
两类对象别混:
- Temporary Table:临时表(常用于 source/sink,作业脚本里即建即用)
- Catalog Table:持久化表(通常配合 HiveCatalog、JDBC Catalog 等)
3.5 execute_sql 与 sql_query:一个"执行",一个"拿 Table"
execute_sql(stmt):执行单条语句(DDL/DML/DQL/SHOW/DESCRIBE/EXPLAIN/USE)sql_query(query):把 SQL 查询结果转成Table(用于继续 Table API 链式处理)
示例:
python
t = table_env.sql_query("SELECT id, SUM(v) AS s FROM T GROUP BY id")
关于 DML 的一个关键点:
execute_sql("INSERT INTO ...")通常是异步提交(远端集群场景更符合预期)- 本地 mini cluster / IDE 调试时经常需要
.wait()等待结束
4. 作业执行与解释计划:explain_sql / StatementSet / 多 Sink
4.1 explain_sql:快速看 SQL 的 AST 与执行计划
当你想确认优化有没有生效(谓词下推、投影裁剪、Join 策略等),优先用:
python
plan = table_env.explain_sql("SELECT ...")
print(plan)
4.2 StatementSet:一次作业写多个 Sink(生产很常用)
你有多个下游(例如同时写 Kafka、ES、Blackhole/Print Debug),别拆多个作业,用 StatementSet:
python
statement_set = table_env.create_statement_set()
statement_set.add_insert_sql("INSERT INTO sink1 SELECT ...")
statement_set.add_insert_sql("INSERT INTO sink2 SELECT ...")
statement_set.execute().wait()
优点:
- 复用同一份 source 与计算链路
- 只提交一个 job,运维更简单
4.3 废弃 API 迁移建议(少走弯路)
这些在新代码里建议不要再用:
| 旧 API | 推荐替代 |
|---|---|
| scan | from_path |
| register_table | create_temporary_view |
| sql_update | execute_sql |
| explain(table=...) | explain_sql / Table.explain / StatementSet.explain |
| execute(job_name) | execute_sql / StatementSet.execute / Table.execute_insert |
5. UDF 管理:Python/Java 函数注册与优先级
TableEnvironment 可以直接注册函数,也可以用 SQL 注册(CREATE FUNCTION)。
常用接口:
create_temporary_function(path, function):临时 Catalog 函数create_temporary_system_function(name, function):临时 System 函数create_java_function(path, function_class_name, ...):注册 Java 函数到 Catalogcreate_java_temporary_function(...)/create_java_temporary_system_function(...)
一个实用规则:
- 临时 system function 如果和 临时 catalog function 同名,system 的优先级更高(更"全局")。
删除相关:
drop_functiondrop_temporary_functiondrop_temporary_system_function
6. Python 依赖管理:让 UDF 在集群里也能找到你的包
很多 PyFlink 作业跑在集群时失败,不是逻辑错,而是 UDF worker 找不到依赖。
TableEnvironment 提供了三套常用方式:
6.1 add_python_file:加单个文件/包/目录到 PYTHONPATH
python
table_env.add_python_file("/path/to/my_udfs.py")
6.2 set_python_requirements:用 requirements.txt 安装三方依赖
python
table_env.set_python_requirements(
requirements_file_path="/path/requirements.txt",
requirements_cache_dir="/tmp/pyflink_cache"
)
适合:numpy/pandas/requests 等依赖要在 worker 端安装。
6.3 add_python_archive:分发压缩包并解压到 worker 工作目录
python
table_env.add_python_archive("/path/my_dep.zip", target_dir="deps")
适合:你打包了模型文件、词典、配置等资源,worker 端需要解压使用。
7. 配置入口:get_config(并行度、作业名、执行语义都在这)
table_env.get_config() 是你调参的总入口。
最常见的两类设置:
7.1 常规配置:并行度、作业名
python
table_env.get_config().set("parallelism.default", "8")
table_env.get_config().set("pipeline.name", "my_first_job")
7.2 容错与状态:StateBackend、Checkpoint、Restart Strategy
现在推荐在 TableConfig 里配置(而不是只在 StreamExecutionEnvironment 配)。
python
# 重启策略:fixed-delay
table_env.get_config().set("restart-strategy.type", "fixed-delay")
table_env.get_config().set("restart-strategy.fixed-delay.attempts", "3")
table_env.get_config().set("restart-strategy.fixed-delay.delay", "30s")
# Checkpoint:Exactly-once
table_env.get_config().set("execution.checkpointing.mode", "EXACTLY_ONCE")
table_env.get_config().set("execution.checkpointing.interval", "3min")
# StateBackend:rocksdb / hashmap
table_env.get_config().set("state.backend.type", "rocksdb")
table_env.get_config().set("execution.checkpointing.dir", "file:///tmp/checkpoints/")
经验建议:
- 开 RocksDB 必须配 checkpoint dir(尤其是文件系统路径/对象存储路径)
- 流作业一定要把 checkpoint 周期、超时、并发数等补齐到生产标准(这里只示例核心项)
8. Catalog 与 Module:多环境、多库、多函数体系的关键
当你接入 HiveCatalog、JDBC Catalog 或自研 Catalog 时,以下 API 很重要:
- Catalog:
register_catalog / get_catalog / use_catalog - Database:
use_database / get_current_database - 列举对象:
list_tables / list_views / list_functions / list_catalogs / list_databases ... - Module:
load_module / unload_module / use_modules / list_modules
典型场景:
- 你希望 SQL 里不写全限定名(catalog.db.table),就用
use_catalog/use_database设置默认命名空间 - 你希望扩展函数解析顺序,就用 module 管理
9. 快速工作流模板:写 PyFlink Table 作业的标准姿势
你可以把自己的项目按这个顺序组织(清晰且可维护):
1)创建 TableEnvironment(streaming/batch + config)
2)设置 TableConfig(并行度、checkpoint、statebackend、作业名)
3)注册 catalog / use catalog / use database(可选)
4)注册 source/sink(DDL 或 TableDescriptor)
5)注册 UDF + 依赖(如有)
6)sql_query 拿 Table 或 Table API 构建链路
7)execute_sql INSERT / Table.execute_insert / StatementSet.execute 提交执行
8)必要时 explain_sql/table.explain 看计划