Reader 的参数决定了「从哪里、按什么条件、用多少并发读」。这一部分写错,轻则读不到数据,重则把源库拖垮。
connection 是数组,每项含 jdbcUrl(可多个做高可用)、table、以及可选的 querySql。能用 querySql 自定义 SQL 时,我们优先用它:可以把 join、过滤、类型转换下推到源库,减少 DataX 侧处理量。但要注意 querySql 和 column/table 二选一,混用会报错。
{ "reader": { "name": "mysqlreader", "parameter": { "username": "etl", "password": "${SRC_PWD}", "connection": [ { "jdbcUrl": ["jdbc:mysql://h1:3306/d", "jdbc:mysql://h2:3306/d"], "querySql": ["select id, name from user where created_at > '2024-01-01'"] } ], "splitPk": "id", "fetchSize": 1000 } } }
splitPk 让表可被分片并发(见 3.1)。fetchSize 控制每次从 JDBC 拉多少行进内存,太小则往返多、太大会撑内存。我们一般设 1000 到 5000,配合 Channel 缓冲一起调。

where 和 querySql 都能过滤,但 where 由插件拼接、querySql 完全自定义。若过滤逻辑复杂(多表 join),用 querySql;若只是单表按时间增量,用 where 更简洁,也利于插件做分片下推。
凡是能下推到源库的计算(过滤、简单转换),我们都尽量下推,因为源库通常索引完备、执行高效,比把全量拉到 DataX 再处理省资源。这条原则让很多任务在源头就瘦了身。
能用 querySql 自定义 SQL 时,我们优先用它把过滤、简单转换下推到源库,减少 DataX 侧的处理量。但要注意 querySql 和 column/table 二选一,混用会报错。单表按时间增量时,用 where 更简洁,也利于插件做分片下推。
| 方式 | 适用 | 注意 |
|---|---|---|
| querySql | 复杂过滤/join | 不能混用 column |
| where | 单表增量 | 利于分片下推 |
| splitPk | 大表并发 | 列要均匀 |
我们坚持「能下推就下推」:源库有索引、执行高效,比把全量拉到 DataX 再过滤省资源。这条原则让很多任务在源头就瘦了身。
星型拓扑把 N 乘 M 的对接降到 N 加 M,变更成本随之下降。
把 DataX 当搬运工而非加工车间,链路才简单可排查。
关系型 Writer 的批量提交大小,要在往返开销和回滚成本间权衡。
插件目录名必须和 job.json 的 name 完全一致,大小写都不能错。
任务的读写速率差,比绝对速率更能说明瓶颈在哪一段。
脏数据阈值设得太高,会掩盖源端的数据质量问题,反而埋雷。
生产环境的稳定性,常常取决于部署习惯而非某个高级特性。
writeMode 必须和数据更新语义对齐,不能凭感觉选。
日志里周期打印的读写速率,是定位瓶颈的第一手材料。
监控指标和 DataX 日志交叉看,能锁定九成瓶颈。
JVM 堆要给 Channel 缓冲留足空间,否则 GC 频繁拖慢吞吐。
源库索引评审应作为同步查询上线的前置环节。
任务可重跑幂等,是生产上线前的硬指标。
对象存储比 FTP 更适合做跨机房中转,因为它支持断点和内网加速。
Reader 和 Writer 互不知晓,正是插件能独立扩展的原因。
orc 加 snappy 是 Hive 落地的常见稳妥组合,省空间且查询快。
测试样本先小后大,几分钟校验能省下几小时排错。
channel 数超过源端连接承受能力时,瓶颈会从 DataX 转移到数据库。
把复杂 join 留在计算引擎,DataX 只做贴源搬运。
一张参数与吞吐的经验曲线,比任何通用公式都贴近你的环境。
反压机制保护内存,看到任务变慢应去优化下游而非加并发。
Redis 同步重跑要防重复 key,靠固定模板才能幂等。
数据湖贴源层保留原始形态,方便后续 schema 演化。
Channel 是有界缓冲,填满即触发反压保护内存。
eswriter 的批量 bulk 写入,比逐条插入快一个数量级。
querySql 与 column 二选一,下面是 querySql 的写法。
{ "reader": { "name": "mysqlreader", "parameter": { "connection": [{ "jdbcUrl": ["jdbc:mysql://h:3306/d"], "querySql": ["select id,name from t where c>0"] }] } } }
Reader 参数直接作用在最前端的抽取环节。写错连接、漏了切分、过滤不对,后面再怎么调优都白搭。我们以 mysqlreader 的典型参数为例。
{ "job": { "content": [ { "reader": { "name": "mysqlreader", "parameter": { "username": "etl", "password": "secret", "connection": [ { "jdbcUrl": ["jdbc:mysql://db:3306/order"], "table": ["t_order"] } ], "column": ["id","user_id","amount","create_time"], "splitPk": "id", "where": "create_time >= '2024-01-01'", "querySql": "", "fetchSize": 1000 } }, "writer": { "name": "streamwriter", "parameter": { "print": false } } } ], "setting": { "speed": { "channel": 8 } } } }
# 4.3 Reader配置参数:数据源连接、查询条件、并发设置 python bin/datax.py job/reader_only_test.json
connection:jdbcUrl + table 或 querySql 二选一;多库同构可并列多个连接;column:指定抽取列,少抽列能显著降 IO;splitPk:并发切分键,整型主键最佳;where:增量 / 过滤条件;fetchSize:JDBC 批次,过大吃内存、过小增交互。这些参数共同决定「抽什么、抽多少、怎么并发」。写对了,下游 Writer 拿到的就是干净、完整、可分片的数据流。
需要多表 join 抽取时,用 querySql 写完整 SQL(如 SELECT a.id, b.name FROM a JOIN b ...),此时 splitPk 要指向结果集里的数值列才能继续并发。
| 参数 | 作用 | 建议 |
|---|---|---|
| connection | 数据源 | 多库并列 |
| column | 抽取列 | 只抽所需 |
| splitPk | 并发键 | 整型主键 |
| fetchSize | 批次 | 500~2000 |
💡 关键直觉:Reader 是整条链路的「水源」,水源的参数错了(列不对、条件不对、不可并发),后面 Writer 写得再快也是徒劳。先保 Reader 正确,再谈优化。
⚠️ 常见坑:table 与 querySql 同时填写,框架以 querySql 优先并忽略 table,容易让人以为在抽 A 表其实在跑 B 查询;二者务必二选一,保持配置自解释。