简介:这份PPT讲解聚焦ETL工具Kettle(即PDI)的基础知识与项目落地,面向具备一定编程基础、工作一至三年的研发人员,尤其适合需要对接MySQL、Oracle等数据库并处理数据同步任务的开发者。内容从“什么是ETL、什么是Kettle”展开,逐步覆盖Kettle安装、目录结构、转换与作业、步骤与跳、数据行及数据类型、数据库连接与注意事项等核心概念;配合PDI 9.2演示关键操作,能让读者明白转换与作业的差异、步骤之间的数据流动方式,了解Kettle在实际项目中的实现路径、常见不足点以及数据同步调优思路。资源包内含1个pptx文件,共26页PPT,压缩包仅859KB,体积轻量,适合按页学习或团队内部分享。目前已有1463人学习下载,对正在入门ETL、需要系统梳理Kettle使用要点并规避常见坑点的开发者有较高参考价值,整体内容较完整,图文结合,便于快速建立Kettle整体认知。
1. ETL 与 Kettle:为什么数据搬运这件事最耗人力
做了几年数据项目之后我发现一个反直觉的规律:数据接入最累的从来不是“从 A 库拷到 B 库”那一下,而是拷贝之前那些没人愿意管的脏活——字段对不上、空值乱飞、编码不统一、同一张表在两个系统里含义不同。ETL 就是把这摊杂活标准化的一套流程,Kettle 则是这套流程里新手最容易拿起来就用的图形化工具。这篇文章按我平时给团队讲 Kettle 基础课的思路写,适合刚接触数据接入、想在本地快速验证抽取清洗方案的开发者和运维。下面不重复官方文档,只讲动手时会真正遇到的东西。
2. Kettle 基础:转换、作业和两类流的最小认知模型
开始点鼠标之前,先把 Kettle 里最容易把新人绕晕的三个概念分清:转换(Transformation)、作业(Job)和跳(Hop)。理解这三样,后面配步骤就不是在黑匣子里瞎试,而是知道每一步到底在做什么。
2.1 转换与作业:一个有图形界面的两个容器
转换对应磁盘上的.ktr文件,作业对应.kjb文件。这个后缀很重要,因为命令行跑批时靠它区分用哪个执行器。
转换的核心特征是数据处理流水线。转换里的执行单元叫步骤(Step),步骤之间用连线(Hop)连接,数据像水一样从上游步骤流到下游步骤。转换的特点一是步骤之间默认并行运行,而不是像写程序一样一行一行顺序执行;二是每条数据经过连线时,Kettle 会把它放在内存的行集(Row Set)里缓冲。这个机制带来的直接后果是:如果下游处理太慢,上游不会无限读数据,缓冲满了会自然背压。
作业则完全不是这套逻辑。作业里的执行单元叫作业条目(Job Entry),它管的是“什么时候该做什么事”的控制流,比如先执行转换 A、再发送邮件、成功了才执行转换 B。作业条目的连线是“上一个做完、并且结果满足条件,才走这条线”的关系,连线上有成功、失败、无条件之分。基础阶段可以简单记:转换管数据处理,作业管流程编排。
这里插一句选型上的常见误区:很多教材强调一定要用作业来调度转换,但实际做数仓接入时,单次一次性同步直接用转换跑就够了;只有涉及多步依赖、失败重试、定时循环时,才需要套一层作业。作业是执行框架,不是所有转换的必需品。
2.2 数据流与控制流:Kettle 里最容易混淆的边界
我见过不少新同事把作业当成“能处理数据的转换”去用,想在作业里直接拖一个“表输入”步骤来做查询,结果发现作业条目列表里根本没有表输入,只有“SQL 脚本”“转换”“发送邮件”这些执行型条目。原因就是刚才说的:作业只管控制流,不做逐行数据处理。
反过来,转换里也不是完全不能有控制逻辑。每个步骤下方有“主输出”“错误处理”两种输出流,比如“表输出”写目标表失败时,错误行会沿错误流走,你可以接一个“文本文件输出”把坏行单独落盘。这算转换内部的轻量分支,但复杂度马上上来,基础阶段不建议一上来就玩多输出流,先把单条主链路跑通。
连线(Hop)上还有一个在图形界面里常被忽略的属性:在连线上“右击 → 编辑跳”→ 修改“发送”和“接受”状态。默认是单向且启用,如果误取消了启用,数据不会流动,现象是跑完转换后目标表没数据,而日志里也没有任何报错。这种“没有报错但没数据”的情况,排查顺序里一定要有“看连线是否停用”这一项。
2.3 一个最小 .ktr 文件长什么样
图形界面拖完保存后,Kettle 会生成 XML。很多新人以为只能靠鼠标操作,一旦要批量生成或做版本对比就无从下手。其实你完全可以打开一个.ktr文件直接看结构。一个只有“CSV 输入 → 表输出”的转换,骨架大概是这样的:
<transformation> <info> <name>user_csv_to_db</name> </info> <step> <name>read_csv</name> <type>CsvInput</type> <encoding>UTF-8</encoding> <filename>${INPUT_FILE}</filename> <delimiter>,</delimiter> <enclosure>"</enclosure> <header>Y</header> <bufferSize>50000</bufferSize> </step> <step> <name>write_db</name> <type>TableOutput</type> <connection>local_mysql</connection> <table>ods_user</table> <commitSize>1000</commitSize> </step> <hop> <from>read_csv</from> <to>write_db</to> <enabled>Y</enabled> </hop> </transformation>这个片段里<type>CsvInput</type>是步骤类型的内部名称,<connection>指向我们在数据库连接里配置的连接名,${INPUT_FILE}则是一个变量占位符,运行时通过命令行传入真实路径。建议每次保存转换后都顺手打开 XML 看一遍字段名,很多界面上的问题其实是配置名写错了,比如连接名带空格导致执行时找不到连接。理解了这个结构,后面用命令行跑转换时,-param传参对到哪里心里就有数了。
3. 从零跑通第一个转换:CSV 入库的六步操作链
纸上概念讲完,直接做第一个能跑出结果的东西:把一份 CSV 文件读进来,简单清洗,写进数据库表。整个过程走通之后,Kettle 的套路就摸到一半了。
3.1 新建转换与输入步骤配置
打开 Kettle 图形界面后,新建一个转换,先把“CSV 文件输入”拖到画布,这是基础课里最推荐作为起点的步骤。它比“文本文件输入”配置简单,没有繁琐的正则切割规则,适合第一次上手。
双击进入配置,需要定几个核心参数:文件路径、分隔符、是否首行作为标题、编码格式。我一般会把文件路径写成变量,比如${INPUT_FILE},而不是写死本机路径。原因很简单:同一个转换在开发机、测试机、生产机上跑,路径一定不一样,写死路径等于每换一次环境就改一次文件。
编码这个选项容易被无视。手头 CSV 是从 Windows 导出的,很可能是 GBK 或 GB18030;从线上 Linux 导出的,一般是 UTF-8。这里选错不会报错,而是导入后字符串字段全变乱码,属于 Kettle 新手第一坑,后面避坑章节专门展开。
参数列表大致如下:
| 配置项 | 建议值 | 说明 |
|---|---|---|
| 文件/目录 | ${INPUT_FILE} | 用变量代替硬编码路径 |
| 分隔符 | , | 与 CSV 实际分隔符严格一致 |
| 头部 | 是 | 首行当列名,可省去后续字段映射 |
| 编码 | UTF-8 / GBK | 看文件本身,别猜,用命令 file 看 |
| 并行读文件 | 否 | 小文件别开,会改变行顺序 |
3.2 字段映射、值映射与输出配置
输入步骤读出来的字段,不一定直接能写进目标表。常见差异有三类:源字段多余目标字段、类型不匹配、值域需要归一化。
我通常会在输入之后拖一个“字段选择”步骤,把不需要的字段裁掉,同时在这里改类型和长度。比如 CSV 里所有字段解析出来默认可能是 String,目标表age是整数,就在这里把age改为 Integer,8长度。
如果源数据里性别存的是1/0,而目标表要求男/女,就在字段选择后面加一个“值映射”步骤:源值1映射为男,0映射为女,目标值是空或异常的保留原值,后面再单独处理。
最后把“表输出”拖进来,配置数据库连接和目标表名。需要注意“表输出”步骤默认行为是追加写入,不是清空重建。如果希望同步前清掉旧数据,要么在转换最前面加一个“执行 SQL 脚本”步骤先TRUNCATE,要么在作业里用作业条目的“SQL 脚本”完成。很多新人直接跑两次转换,发现目标表数据翻倍,就是这个默认行为没搞清楚。
3.3 在命令行用 Pan 跑转换
图形界面里点“运行”能直接看到结果,但真实场景中,转换要被定时任务调用,必须学会命令行执行。Kettle 安装目录下有两个执行器:pan.sh(对应 Windows 的pan.bat)跑转换,kitchen.sh(对应kitchen.bat)跑作业。
# 切换到 Kettle 安装目录 cd /opt/kettle/data-integration # 执行转换,传入输入文件变量,日志级别用 Basic ./pan.sh -file:/data/etl/user_csv_to_db.ktr \ -param:INPUT_FILE=/data/etl/input/user.csv \ -level:Basic参数说明:-file指定转换文件绝对路径;-param用来传变量,格式是-param:变量名=值,一个-param只能传一个变量,多个变量就写多个-param;-level控制日志明细,基础运行用Basic,排查数据问题时切到Rowlevel,但逐行输出日志在数据量大时能把人卡死,平时不要用。
这里还有个容易踩的位置:在 Windows 上跑要写pan.bat,而且路径里有空格时最好用引号把-file值包起来。如果嫌命令行输出乱码,先执行chcp 65001切换到 UTF-8 代码页再运行。
4. 高频步骤的参数取舍:表输入、排序合并与增量同步
第一个转换跑通之后,接下来你接触最多的业务场景大概率的不是 CSV,而是库表之间的搬运和比对。这一章讲三组高频步骤:表输入与表输出、排序与去重、合并记录,并给出参数到底该怎么设。
4.1 表输入与表输出:SQL 写在哪、分页怎么设
如果你面对的数据在数据库里,就别绕道 CSV 了,直接用“表输入”步骤。“表输入”的本质是一个 SQL 查询执行器,查询结果就是数据流。配置时分两步:选好数据库连接,然后写 SQL。
在实际项目里,我很少在表输入里写整张表SELECT *,而是把过滤条件尽量留在 SQL 里下推给数据库。比如同步updated_at大于上次时间的增量数据,就直接写进 SQL:
SELECT id, user_name, age, updated_at FROM source_user WHERE updated_at > '${LAST_RUN}'这段 SQL 里的${LAST_RUN}是 Kettle 变量,运行时会被替换成上次同步时间戳。原则是“能在 SQL 里过滤的,不要等数据全量拉回来再用步骤过滤”,Kettle 的过滤步骤虽然好用,但数据已经过一次网络传输了,性能差距在高并发拉大表时非常明显。
表输出的参数是性能核心,重点看提交记录大小和批量插入两个配置:
| 参数名 | 作用 | 我常用的设置 |
|---|---|---|
| 提交记录大小 | 攒够多少行一次性提交事务 | 500~2000,小表 500,大表 2000 |
| 使用批量插入 | 走 JDBC 批处理,大幅减少网络往返 | 开启 |
| 表名 | 目标表名 | 写完整表名,不要带库名前缀 |
| 忽略插入错误 | 出错时跳过继续跑 | 默认关闭,留着错误流接日志 |
提交记录大小的道理和批量插入类似:默认值偏保守,每次写一行就提交一次,事务开销全耗在提交上。调大后,目标表的写入表现会明显上一个台阶。但如果你用的是 MySQL 且对端开了 binlog,批量插入会产生大量单条 binlog 事件,同步期间目标库的从库延迟可能升高,这属于要权衡的副作用。
4.2 排序去重与合并记录:什么时候交给内存,什么时候退给数据库
Kettle 里做去重有两种常见组合:一种是“排序去重”,先按主键排序,再用“唯一行”步骤去重;另一种是“按字段值去重”,它不要求排序,但只能保留首次出现的行。前者适合大表,后者适合小数据量、且不关心顺序的场景。
排序步骤有个关键参数:排序缓冲区大小(也就是内存里最多缓存多少行)。默认配置偏保守,几十万行以内没事,上千万行不做调优就可能触发内存问题。直接用“排序”步骤时,我一般先看数据量估算:单表超过 500 万行,优先在表输入的 SQL 里ORDER BY并用数据库的索引来排,而不是拉回来让 Kettle 排。数据库擅长的事别买 单,这是 ETL 调优的第一原则。
合并记录(Merge Rows)是增量同步和表对比里最常用的步骤。它要求两个输入:一个是参考流,一个是对比流,两路都先按关键字排序,然后逐行比较。配置要点如下:
| 配置项 | 含义 | 注意点 |
|---|---|---|
| 参考输入(Reference) | 一般是目标表已有数据 | 必须与对比流排序规则一致 |
| 对比输入(Comparison) | 一般是源表新数据 | 字段集合要和参考流一致 |
| 关键字段(Keys) | 业务主键,如 user_id | 只做匹配,不比较差异 |
| 比较字段(Values) | 需要比对内容的字段,如 name | 空值会被视为不相等,先预处理 |
| 标志字段(Flag) | 输出差异标记列 | 值为 identical / new / changed / deleted |
这个步骤是理解 Kettle 数据流的好样本:它不改变数据本身,而是给每行打标签。真正的动作在标签之后的“过滤记录”步骤里:把 flag 为new的行导到表输出做插入,changed的行导到更新步骤,deleted的行按需处理。没有这一步,合并记录只是看个热闹。
4.3 数据校验与空值处理:脏数据就地拦截
数据清洗里最烦的是空值。Kettle 里空值不是统一的NULL,可能是空字符串、空格、字符串"NULL"三种形态。基础阶段用一个“值映射” + 一个“空值替换”步骤组合处理:值映射把"NULL"这类字面量映射成空串,然后再把空串统一替换成真正的NULL或业务默认值。
这里容易犯的毛病是在转换中间某一步处理了空值,却发现下游步骤里的空值又回来了。原因多半是“计算器”或“字段选择”步骤重新生成了字段,新字段默认不继承上游的空值处理。字段选择里改名、改类型后,建议立即接一个“空值替换”步骤再把关一道,别指望流程后面还有机会补救。
5. Kettle 避坑手册:编码、提交、驱动与合并的四场实战
这一章是血泪经验汇总。前四章讲怎么做,这一章讲的是做了之后为什么翻车,以及翻车时看哪里。
5.1 中文乱码:CSV 读进来到处都是“?”
现象:CSV 里的中文通过“CSV 文件输入”读进来,预览时已经乱码,写进数据库后变成???或者彻底不可读。排查半天最后发现三个地方的编码没对齐:CSV 文件本身是 GBK、输入步骤里设的是 UTF-8、数据库连接字符集又是 latin1 之类。
原因:Kettle 每个步骤、每个数据库连接都有独立的字符集设置,任何一个环节断掉,就乱码。很多人只改输入步骤,忽略了数据库连接 URL 里的字符集参数。
解决:先把 CSV 文件用文本编辑器或file命令确认真实编码,输入步骤选对应编码;再把数据库连接的连接参数里加上characterEncoding=utf8。实践中我遇到最多的组合是“文件 GBK + 数据库 UTF-8”,这种场景不要在输入步骤里写死 UTF-8,直接把文件另存为 UTF-8 再做,省得中间步骤反复转码。
5.2 表输出慢得离谱:几千行写了几分钟
现象:一个只有 3000 行的转换,前几步秒完,到表输出像卡死一样,日志里没有任何错误。
原因:表输出的提交记录大小用了默认值,并且“使用批量插入”没开。Kettle 每攒够一次提交就发一次事务,逐行提交时数据库端每行都要同步一次落盘,几千行就产生几千次事务往返,慢是必然的。
解决:把提交记录大小调到 1000 以上,打开批量插入,再跑一次基本能快一到两个数量级。这里要提醒,批量插入对目标端数据类型隐式转换容忍度低,如果源数据类型和目标字段类型不一致,会从“慢”变成“报错”。所以先保证字段映射类型正确,再开批量。
5.3 数据库驱动与连接参数:连不上 MySQL 的经典翻车
现象:新建 MySQL 连接时点测试,报Class not found,或者提示The server time zone value ...无法识别。
原因:一是 Kettle 自带的 lib 目录里没有对应版本驱动 jar,MySQL 8 的驱动类名和旧版都不一样;二是新版 MySQL 驱动要求 URL 带上时区参数。
解决:先把对应版本的 JDBC 驱动 jar 放进style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />