Kettle多环境ETL怎么做?一套参数化转换搞定6个数据中心
📌前言:在金融行业做数据开发,多环境、多数据中心是常态。最近一个银行项目,6个区域分行的数据仓库结构完全相同,只是表名后缀不同。如果为每个分行各做一套ETL,维护成本直接翻6倍。本文分享如何用Kettle的参数化机制,1套转换文件服务6个数据中心。
一、项目背景
某全国性商业银行,在全国6个区域分行各有独立的业务系统:
| 分行 | 标识 | 数据库 |
|---|---|---|
| 华东分行 | huadong | db_huadong |
| 华南分行 | huanan | db_huanan |
| 华北分行 | huabei | db_huabei |
| 西南分行 | xinan | db_xinan |
| 东北分行 | dongbei | db_dongbei |
| 西北分行 | xibei | db_xibei |
每个分行的ODS层表结构完全相同,只是表名带分行后缀:
ods_account_huadong ods_account_huanan ods_account_huabei ... ods_transaction_huadong ods_transaction_huanan ods_transaction_huabei ... ods_customer_huadong ods_customer_huanan ods_customer_huabei ...DM层也是同样的命名规则:
dm_risk_assessment_huadong dm_risk_assessment_huanan ...此外还有一个合并DM表dm_risk_assessment,汇总6个分行的数据供总行使用。
二、最初的方案:6套ETL?
如果为每个分行各做一套转换文件:
- 6个分行 × 5个ODS表 × 1个DM表 =30个转换步骤
- 每次修改逻辑需要改6遍
- 极易遗漏,导致分行间逻辑不一致
这显然不可接受。
三、参数化方案:1套转换 + 变量替换
3.1 核心思路
- 创建1个转换文件,SQL中的表名使用
${ENV_NAME}变量 - 在作业中创建6个"转换"作业项,每个传入不同的
ENV_NAME参数值 - 修改逻辑时只改1个文件,6个分行自动生效
3.2 转换文件设计
以ODS→DM的转换为例,创建dm_batch_insert.ktr:
SQL中的变量使用:
INSERTIGNOREINTOdm_risk_assessment_${ENV_NAME}(account_id,customer_name,risk_cate1,risk_cate2,risk_cate3,risk_cate4,product_cate1,product_cate2,product_cate3,product_cate4,trans_id,trans_name,trans_code,method_name,create_time,update_time)SELECTa.account_id,a.customer_name,a.cate1,a.cate2,a.cate3,a.cate4,NULL,NULL,NULL,NULL,t.trans_id,t.trans_name,m.code,m.nameASmethod_name,NOW(),NOW()FROMods_account_${ENV_NAME} aINNERJOINods_transaction_${ENV_NAME} trONa.account_id=tr.account_idLEFTJOINods_trans_detail_${ENV_NAME} tONtr.trans_id=t.trans_idLEFTJOINods_stand_item_${ENV_NAME} siONt.item_id=si.item_idLEFTJOINods_stand_method_${ENV_NAME} mONsi.method_id=m.method_idWHEREtr.update_time>'${LAST_SYNC_TIME}';转换参数定义(右键画布 → 转换设置 → 参数):
| 参数名 | 默认值 | 描述 |
|---|---|---|
ENV_NAME | huadong | 分行标识 |
LAST_SYNC_TIME | 2026-01-01 00:00:00 | 上次同步时间 |
3.3 作业文件设计
在作业中创建6个"转换"作业项,每个引用同一个dm_batch_insert.ktr,传入不同的参数:
START → DM_HUADONG → DM_HUANAN → DM_HUABEI → DM_XINAN → DM_DONGBEI → DM_XIBEI → 成功每个作业项的参数配置:
| 作业项名称 | 转换文件 | ENV_NAME | LAST_SYNC_TIME |
|---|---|---|---|
| DM_HUADONG | dm_batch_insert.ktr | huadong | ${LAST_SYNC_TIME} |
| DM_HUANAN | dm_batch_insert.ktr | huanan | ${LAST_SYNC_TIME} |
| DM_HUABEI | dm_batch_insert.ktr | huabei | ${LAST_SYNC_TIME} |
| DM_XINAN | dm_batch_insert.ktr | xinan | ${LAST_SYNC_TIME} |
| DM_DONGBEI | dm_batch_insert.ktr | dongbei | ${LAST_SYNC_TIME} |
| DM_XIBEI | dm_batch_insert.ktr | xibei | ${LAST_SYNC_TIME} |
关键配置:每个转换作业项必须 ✅ 勾选"从上一个结果复制参数",这样${LAST_SYNC_TIME}才能从作业级别传递到转换级别。
四、参数传递的完整链路
理解Kettle的参数传递机制是参数化方案的关键:
主作业 (LAST_SYNC_TIME=2026-04-23 00:00:00) │ ├─→ Step2作业 (继承LAST_SYNC_TIME) │ ├─→ ODS_HUADONG转换 (ENV_NAME=huadong, 继承LAST_SYNC_TIME) │ ├─→ ODS_HUANAN转换 (ENV_NAME=huanan, 继承LAST_SYNC_TIME) │ └─→ ... │ ├─→ Step3作业 (继承LAST_SYNC_TIME) │ ├─→ DM_HUADONG转换 (ENV_NAME=huadong, 继承LAST_SYNC_TIME) │ ├─→ DM_HUANAN转换 (ENV_NAME=huanan, 继承LAST_SYNC_TIME) │ └─→ ... │ └─→ Step4作业 └─→ DATA_QUALITY转换4.1 参数传递规则
- 作业→子作业:子作业勾选"从上一个结果复制参数"即可继承
- 作业→转换:转换作业项勾选"从上一个结果复制参数"
- 转换→步骤:步骤勾选"替换变量",SQL中的
${VAR}自动替换 - 作业项级别参数:优先级最高,会覆盖继承的参数
4.2 参数优先级
作业项级别参数 > 作业级别参数 > 转换级别默认值例如,DM_HUADONG作业项中设置了ENV_NAME=huadong,即使转换的默认值是huadong,作业项的设置也会优先生效。
五、ODS层:6个分行并行执行
ODS层的6个分行之间没有依赖关系,可以并行执行:
START ──→ ODS_HUADONG ──→ 成功 ──→ ODS_HUANAN ──→ 成功 ──→ ODS_HUABEI ──→ 成功 ──→ ODS_XINAN ──→ 成功 ──→ ODS_DONGBEI ──→ 成功 ──→ ODS_XIBEI ──→ 成功在Kettle作业中,从START节点画多条Hop线到不同作业项,它们会自动并行执行。
六、DM层:6个分行顺序执行
DM层的处理需要创建临时表来拆分逗号分隔的字段,如果并行执行会导致临时表冲突。因此必须顺序执行:
START → DM_HUADONG → DM_HUANAN → DM_HUABEI → DM_XINAN → DM_DONGBEI → DM_XIBEI → 成功⚠️为什么不能并行:每个DM转换都会创建→使用→删除临时表
temp_trans_split。如果两个分行并行执行,分行A刚创建的临时表可能被分行B删掉,导致数据错乱。
七、合并DM表:UNION ALL汇总
6个分行的DM表处理完成后,需要将数据汇总到合并表供总行使用:
INSERTIGNOREINTOdm_risk_assessment(account_id,customer_name,risk_cate1,risk_cate2,risk_cate3,risk_cate4,product_cate1,product_cate2,product_cate3,product_cate4,trans_id,trans_name,trans_code,method_name,create_time,update_time)SELECT...FROMdm_risk_assessment_huadongWHEREcreate_time>='${CURRENT_SYNC_TIME}'UNIONALLSELECT...FROMdm_risk_assessment_huananWHEREcreate_time>='${CURRENT_SYNC_TIME}'UNIONALLSELECT...FROMdm_risk_assessment_huabeiWHEREcreate_time>='${CURRENT_SYNC_TIME}'UNIONALLSELECT...FROMdm_risk_assessment_xinanWHEREcreate_time>='${CURRENT_SYNC_TIME}'UNIONALLSELECT...FROMdm_risk_assessment_dongbeiWHEREcreate_time>='${CURRENT_SYNC_TIME}'UNIONALLSELECT...FROMdm_risk_assessment_xibeiWHEREcreate_time>='${CURRENT_SYNC_TIME}';这个转换单独创建为refresh_combined_dm.ktr,放在6个分行DM处理之后执行。
八、方案对比
| 对比项 | 6套独立文件 | 1套参数化文件 |
|---|---|---|
| 转换文件数量 | 6×5=30个 | 5个 |
| 修改逻辑 | 改6遍 | 改1遍 |
| 遗漏风险 | 高 | 无 |
| 新增分行 | 复制+改表名 | 加1个作业项 |
| 维护成本 | 高 | 低 |
九、踩坑提醒
9.1 变量替换必须勾选
每个"执行SQL脚本"步骤都要勾选"替换变量",否则${ENV_NAME}不会被替换,SQL会报语法错误。
9.2 参数传递必须勾选"从上一个结果复制参数"
作业项如果不勾选这个选项,子转换/子作业就拿不到父级传递的参数。
9.3 变量在SQL中的引号
字符串类型的变量在SQL中需要加引号:
WHEREupdate_time>'${LAST_SYNC_TIME}'-- ✅ 有引号WHEREupdate_time>${LAST_SYNC_TIME}-- ❌ 没引号,SQL语法错误数字类型的变量不需要加引号:
WHEREidBETWEEN${BATCH_START_ID}AND${BATCH_END_ID}-- ✅ 数字不加引号9.4 默认值是调试用的
转换参数的默认值只是方便在Spoon中单独测试,实际运行时由作业传入的参数覆盖。
十、总结
核心要点:
- 多环境ETL用参数化转换,1套文件服务N个环境
- 表名用
${ENV_NAME}变量,作业中传入不同值 - 参数传递链路:主作业 → 子作业 → 转换 → SQL步骤
- 无依赖的步骤可以并行,有临时表冲突的必须顺序
- 合并表用UNION ALL汇总各环境数据
💡一句话总结:别为每个环境做一套ETL了,参数化才是多环境数据仓库的正确打开方式!
如果这篇文章对你有帮助,点赞收藏不迷路~ 多环境ETL还有什么好方案?欢迎评论区交流!