数据同步写 Oracle 表耗时 25 分钟缩短到 23 秒——SeaTunnel 性能优化
本文主要给大家介绍JDBC Source批处理任务动态切分优化,希望大家批评指正

JDBC Source 如果配置了table_path
和 partition_column
,引擎会对数据进行动态切分,可以通过分析样本数据优化切分区间,规避数据倾斜问题。
目前发现任务即使配置了where_condition
,动态切分算法仍然会把数据进行全表切分,在从大表中读取少量数据的场景下,任务切分阶段会耗费大量的时间,需要修改下面相关的流程进行优化。
下面所有出现 SQL 语句的地方均以 MySQL 为例子进行说明,具体不同的数据源有不同的子类方法overwrite
实现。
数据切分主流程

数据动态切分的代码入口位于DynamicChunkSplitter
类中的splitTableIntoChunks
方法,流程图中标红的方框表示需要修改的部分,详细在下面的子流程中展开说明。
查询最大最小值

需要加上 Source 的where_condition
配置的判断和拼接。
通用字段切分

查询数据总条数部分
(1)增加且where_condition
配置为空才走“是”的分支
(2)修改“否”分支,增加where_condition
的判断和对应查询语句的拼接,子查询和表查询的规则如下:
如果配置了 Query 则查询 SQL 为
SELECT COUNT(*) FROM (<子查询>) T
否则查询 SQL 为
SELECT COUNT(*) FROM <表名>
如果配置了
where_condition
则拼接到末尾
切分数据区间部分
详情见子流程
分页查询分片
查询下一个分片的结束边界 nextChunkEnd

1.max 查询部分
判断如果配置了 where_condition 则在 limit 那层查询添加条件拼接
2.min 查询部分
判断如果配置了 where_condition 则添加条件拼接
样本查询分片

判断如果配置了where_condition
则添加条件拼接
日期字段切分

复用了通用字段切分
的 1 部分,只需修改一次即可。
分片使用流程
这里相关的流程不需要修改,这里分析是为了弄清楚分片是如何被使用的,以评估前面修改的必要性、正确性和风险。
数据被切分为分片后会被分发到 Worker 的SourceSeaTunnelTask
中,最终在JdbcInputFormat
类的open
方法中被使用,主要流程如下

由上面流程可知,由分片生成的 SQL 在最后会判断拼接where_condition
,如果在生成分片的阶段没有考虑where_condition
,则生成的分片中可能有部分分片在追加上where_condition
条件限制后查询不到数据,当这样的分片很多时,不但会影响分片切分的性能,也会影响数据读取的性能,因为过程中产生了大量的无效查询。
优化效果
优化之后本地测试从一个 55G 的 MySQL 表使用where_condition
过滤读取多条数据的耗时从 25 分钟缩短到 23 秒。
提交的 PR 链接:https://github.com/apache/seatu
评论