提示:Windows 下如果双击 Spoon.bat 一闪而过,不要直接放弃。打开 cmd,cd 到># 在 Spoon.sh 中找到这行,修改 -Xmx 和 -Xms PENTAHO_DI_JAVA_OPTIONS="-Xms2048m -Xmx4096m -XX:MaxPermSize=512m"
参数说明:-Xms是初始堆大小,设成和-Xmx一样可以避免堆动态扩展带来的性能抖动;-Xmx是最大堆,建议不超过物理内存的 50%,给操作系统和其他进程留余量;-XX:MaxPermSize在 JDK 8 里控制永久代大小,JDK 11 之后这个参数会被忽略,不用纠结。改完保存,重启 Spoon 生效。
3. 用 Spoon 画第一条 Transformation:从 CSV 到 MySQL 的完整链路 环境配好之后,真正体现 Kettle 价值的地方是 Transformation 的设计。这一章用一个实际场景串起来:把一份 CSV 文件里的用户数据,经过字段清洗和格式转换,写入 MySQL 表。整个过程在 Spoon 里拖拽完成,不需要写一行 Java。
3.1 新建 Transformation 与 CSV 输入配置 打开 Spoon,File → New → Transformation,画布就出来了。左侧 Core Objects 里找到CSV Input,拖到画布上,双击配置。
关键参数在File标签页:文件名、列分隔符、编码。我一般会显式指定编码为 UTF-8,因为 CSV 文件如果带 BOM,Kettle 读第一列时会多出\ufeff,导致后续字段匹配失败。在Content标签页里,把分隔符设为逗号,Enclosure设为双引号,Header row present勾上,这样 Kettle 会自动用第一行做字段名。
Fields标签页是重点。点Get Fields按钮,Kettle 会预览前几行并推断类型。但自动推断经常把数字识别成 String,把日期识别成 String。我一般会手动改:
字段名 类型 格式 说明 user_id Integer # 用户 ID,整数 user_name String 用户名,允许空 reg_date Date yyyy-MM-dd 注册日期,指定格式 amount Number #.## 金额,保留两位小数
日期格式一定要和 CSV 里的实际格式一致,否则 Kettle 会返回 null 并记一条错误日志。如果 CSV 里日期是2024/01/15,格式就得写yyyy/MM/dd,不能想当然。
3.2 字段清洗与转换步骤的串联 CSV 输入后面接两个步骤:String Operations和Calculator。前者用来去掉用户名前后的空格,后者用来给金额加一个 10% 的折扣列。
从 CSV Input 拖一条线到 String Operations,双击配置:选择user_name字段,勾选Trim类型,两边都去空格。再拖一条线到 Calculator,新建一个计算字段discount_amount,计算类型选A * B,字段 A 选amount,字段 B 填常量0.9。
这里有个细节:Calculator 的常量输入框里直接写0.9就行,不要写成0.9带引号,否则会被当成字符串导致计算报错。步骤之间的连线代表数据流向,Kettle 会按连线顺序逐行处理,不需要额外写循环。
3.3 输出到 MySQL:驱动、连接与批量提交 最后一步是Table Output。拖到画布上,从 Calculator 连过去。双击配置连接:
-- 先在 MySQL 里建好目标表 CREATE TABLE user_discount ( user_id INT PRIMARY KEY, user_name VARCHAR(64), reg_date DATE, amount DECIMAL(10,2), discount_amount DECIMAL(10,2) );然后在 Table Output 里新建数据库连接:Connection type 选 MySQL,Host 填 IP,Database 填库名,Port 默认 3306,用户名密码按实际填。填完点Test,如果报No suitable driver found,说明 MySQL 驱动 jar 没放对位置。
Kettle 9.3 的lib目录里默认不带 MySQL 驱动,需要自己下载mysql-connector-java-8.0.xx.jar丢进去,然后重启 Spoon。驱动版本要和 MySQL 服务端匹配,8.0 的驱动连 5.7 的库一般没问题,反过来可能会报时区错误,需要在连接串里加serverTimezone=Asia/Shanghai。
Table Output 的Target table填user_discount,勾选Specify database fields,把输入字段和目标字段一一对应。Commit size建议设成 1000,意思是每 1000 行提交一次事务。设太小频繁提交影响性能,设太大事务日志膨胀,回滚代价高。我一般处理百万级数据时设 5000,几十万行设 1000 就够。
配置完点画布上方的运行按钮,Spoon 会弹出执行窗口,显示每一步的读写行数、耗时和错误数。如果某一步错误数为 0 且写入行数和 CSV 行数一致,这条 Transformation 就算跑通了。
4. Job 调度与避坑:那些让我重跑三遍的细节 Transformation 跑通只是单次执行,生产环境需要 Job 来串联多个转换、加条件判断和错误处理。这一章把 Job 的用法和实际踩过的坑一起讲,每条都是真实翻车记录。
4.1 Job 的 Start、Transformation 与条件分支 新建 Job,画布上默认有一个Start步骤。从 Start 拖线到Transformation步骤,双击选择刚才保存的 ktr 文件。再拖一个Success步骤接在后面,表示转换成功后执行什么。
Job 里的连线有颜色区分:绿色代表成功,红色代表失败。右键连线可以设置Evaluation条件,比如根据上一步的返回值决定走哪条分支。常见做法是:Transformation 成功 → 发邮件通知;失败 → 写错误日志并重试一次。
# 用 Kitchen 命令行执行 Job,适合放进 crontab /opt/pdi-ce-9.3/data-integration/kitchen.sh \ -file=/data/jobs/daily_sync.kjb \ -level=Basic \ -logfile=/data/logs/daily_sync_$(date +%Y%m%d).log参数说明:-file指定 Job 文件路径;-level控制日志级别,Basic 只记录关键信息,Debug 会打印每行数据,生产环境别用 Debug;-logfile把日志写到指定文件,方便后续排查。这条命令放进 crontab 就能每天定时跑。
4.2 避坑:五个让我重跑三遍的典型问题 现象一:Spoon 启动后界面乱码,菜单全是方块。 原因:Linux 服务器没有装中文字体,或者LANG环境变量没设对。 解决:安装fontconfig和中文语言包,或者在 Spoon.sh 里加-Dfile.encoding=UTF-8,重启后菜单恢复正常。
现象二:CSV 输入步骤报Couldn't find field [xxx]。 原因:CSV 文件第一行有 BOM 头,Kettle 把\ufeffuser_id当成了字段名。 解决:用 Notepad++ 或sed去掉 BOM,或者在 CSV Input 的Content标签页里把Encoding显式设为UTF-8,并勾选Ignore BOM(部分版本叫Skip BOM)。
现象三:Table Output 写入 MySQL 时中文变成问号。 原因:数据库连接串没有指定字符集,或者 MySQL 服务端默认字符集是 latin1。 解决:在连接配置的Advanced标签页里,把characterEncoding设为utf8,同时在 MySQL 里执行SHOW VARIABLES LIKE 'character%'确认服务端字符集。
现象四:Transformation 在 Spoon 里跑正常,用 Pan 命令行执行就报错。 原因:Spoon 启动时会加载lib目录下所有 jar,而 Pan 只加载部分,某些插件依赖的 jar 没被引入。 解决:把缺失的 jar 包复制到lib目录,或者在 Pan.sh 里用-extraClasspath参数手动指定。我一般会把所有数据库驱动统一放lib,避免 Spoon 和 Pan 行为不一致。
现象五:Job 执行到一半卡住,日志停在某一步不动。 原因:数据库连接池耗尽,或者某一步在等待一个永远不会到达的输入行。 解决:先看logs目录下的日志,确认卡在哪一步。如果是数据库连接问题,检查连接池配置和数据库最大连接数;如果是数据流问题,给关键步骤加Timeout设置,超时后走错误分支而不是无限等待。
注意:Kettle 的日志级别在 Spoon 里改是临时的,用 Kitchen 或 Pan 执行时要在命令行加-level参数,否则默认只输出 Error,排查问题时信息不够。
5. 进阶技巧:用变量和参数让同一份转换适配多环境 开发环境连测试库,生产环境连正式库,如果每次都要改连接配置再重新保存 ktr 文件,迟早会改错。Kettle 的变量和参数机制就是解决这个问题的。这一章讲怎么把数据库连接、文件路径、日期范围都做成可替换的参数,让一份 Transformation 在多个环境里复用。
5.1 在 Transformation 里定义参数与变量 打开 Transformation 的Transformation properties,在Parameters标签页里新增参数,比如DB_HOST、DB_NAME、START_DATE。然后在数据库连接配置里,把 Host 填成${DB_HOST},Database 填成${DB_NAME}。Kettle 在执行时会用实际传入的值替换这些占位符。
用 Pan 命令行执行时传入参数:
/opt/pdi-ce-9.3/data-integration/pan.sh \ -file=/data/trans/user_sync.ktr \ -param:DB_HOST=192.168.1.100 \ -param:DB_NAME=prod_db \ -param:START_DATE=2024-01-01 \ -level=Basic逻辑说明:-param:后面跟参数名和值,Kettle 会把 ktr 文件里的${DB_HOST}替换成192.168.1.100。这样同一份 ktr 文件,开发环境传测试库地址,生产环境传正式库地址,不需要改文件内容。
5.2 用 Kitchen 做增量抽取:时间戳变量的实际用法 增量抽取是 ETL 里最常见的需求:每次只抽上次同步之后新增或修改的数据。做法是在 Job 里先查目标库的最大时间戳,赋值给变量,再传给 Transformation 作为过滤条件。
Job 里的步骤顺序:Start→Table Input(查SELECT MAX(update_time) FROM target_table)→Set Variables(把结果赋给LAST_SYNC_TIME)→Transformation(在 Table Input 里用WHERE update_time > '${LAST_SYNC_TIME}'过滤)。
-- 目标库里查最大时间戳的 SQL SELECT COALESCE(MAX(update_time), '1970-01-01 00:00:00') AS max_time FROM target_table;COALESCE的作用是当表为空时返回一个默认时间,避免变量为 null 导致后续 SQL 报错。Set Variables步骤里把max_time字段的值赋给变量LAST_SYNC_TIME,作用域选Valid in the whole JVM,这样后面的 Transformation 才能读到。
5.3 验证与监控:怎么确认数据真的同步对了 跑完 Job 不能只看日志里有没有 Error,还得验证数据一致性。我一般会做三层检查:
第一层,行数比对。在目标库里执行SELECT COUNT(*) FROM target_table WHERE update_time > '${LAST_SYNC_TIME}',和源库的增量行数对比,差值为 0 才继续。
第二层,抽样比对。随机取 10 条源库记录,在目标库里按主键查出来,逐字段对比。这一步能发现字段映射错位、类型转换截断等问题。
第三层,用 Kettle 自带的Data Validator步骤。在 Transformation 末尾加一个 Data Validator,配置需要校验的字段和规则(比如非空、范围、正则),校验失败的行会输出到单独的错误流,方便定位。
从那以后我每次上线新的同步任务,都会先跑一遍全量,再跑一遍增量,对比两次结果是否一致。这个习惯帮我拦住了至少三次字段映射错误。希望帮到你。
本文还有配套的精品资源,点击获取
需要专业的网站建设服务?
联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标
立即咨询