当前位置:文档之家› kettle应用实践(转)

kettle应用实践(转)

kettle应用实践(转)
今天早上在网上看到了kettle发布了最新的版本,忽然想起最近其实做了不少工作应该是ETL工具的拿手好戏,赶紧下载下来看看,看是否能够在实际的工作中应用起来。

顺便讲一下,为啥看到kettle会两眼发光。

最近写了好几个小程序,用于从一个ftp去获取数据,然后转发至另一个ftp去,或者是从一个数据库获取数据然后保存至本地的数据库中,使用的是jdk中的Timer实现的定时调度,本来也没什么问题,连续运行几个月都不会出错。

可是最近网络不是太好,周期性抽风,ping包时,每5分钟大概
会丢7-8个包,从而导致程序也会假死,过一段时间后就不正常干活了,估计是因为用了数据库连接池的问题,要是每次发起数据库连接可能就不会有问题了,偷懒也不想改了,因为网络最终肯定是会修好的 :-) 但是想试试ETL工具,因为后面还有一些类似的东西要处理,不想写代码了,用别人的轮子感觉比较好,呵呵
首先下载了kettle的最新版,kettle3.1,解压后即可运行,一般的开发人员稍微摸索一下,看看例子简单的转换还是会做的,今天小试了一把,有几个注意点记下来。

1.使用资源库(repository)登录时,默认的用户名和密码是admin/admin
2.当job是存放在资源库(一般资源库都使用数据库)中时,使用
Kitchen.bat执行job时,需使用如下的命令行:
Kitchen.bat /rep kettle /user admin /pass admin /job job名
3.当job没有存放在资源库而存放在文件系统时,使用Kitchen.bat执行
job时,需使用如下的命令行:
Kitchen.bat /norep /file user-transfer-job.kjb
4.可以使用命令行执行job后,就可以使用windows或linux的任务调度来
定时执行任务了
在一开始使用命令行方式执行job时,总是报如下的错误,琢磨了好长时间总算整明白正确的方式了。

Unexpected error during transformation metadata load
No repository defined!
下一步准备按照实际情况定制Job,做好了再写小结。

问答:Unexpected error during transformation metadata load
No repository defined!
这个问题你最后怎么解决的?
@吴悔
一开始我是将Job和Transfomation都是存放在资源库中的,然后使用Kitchen.bar执行时会报上述错误,后来登录kettle时,选择“不使用资源库”,直接将Job和Transfomation保存在本地文件中,再使用Kitchen.bat执行就没有问题了。

Kettle的第一个实践--从FTP上取文件,再放至另一个FTP上
这个实践其实不难,主要是有一个地方要注意,就是文件名通配符的写法,如果文件名格式为“TRANS_yyyymmdd.txt”,如TRANS_20081101.txt。

如果想匹配所有以TRANS开头的文本文件,在kettle中要写成这样:
TRANS_.*[0-9].txt。

最后在windows操作系统中配置定时任务就可以定期执行该Job了。

Job的图:
FTP配置信息:
Kettle的第二个实践--数据获取并转换
需求:
kettletest1数据库中有table_source数据表,结构如下:
1.Id 主键
2.t_id 数据时间
3.part_id 实例ID
4.yg 数据字段1
5.wg 数据字段2
该表中的数据对于不同的实例ID,一分钟一条数据,t_id字段表示数据的时间,精确到分钟。

kettletest2数据库中有table_target数据表,结构如下:
1.Id 主键
2.marketdate 数据日期,格式为 yyyy-MM-dd
3.pointtime 时间,格式为 HH:mm
4.pointnumber 时间的数字表示,00:01表示为1,00:00表示为1440
5.plantcode 实例Code
6.yg 数据字段1
7.wg 数据字段2
需定期将table_source表中的数据获取至table_target表中,并进行如下处理:
1、将t_id数据时间字段拆分为三个字段,分别为marketdate、pointtime、pointnumber。

a、marketdate取t_id的日期部分。

b、pointtime取t_id的时间部分。

c、pointnumber为时间的数字表示,等于hour*60+minute。

d、但当t_id的时间为某日的00:00时,需将其转化为24:00,并且marketdate需取日期的前一天。

如t_id为2008-12-04 00:00,则marketdate 为2008-12-03,pointtime为24:00,pointnumber为1440。

2、将part_id字段映射为plantcode字段,并根据如下规则进行转换:
part_id plantcode
3206 P01
3207 P02
3208 P03
测试中使用的数据库均为mysql数据库。

实战:
整个转换工作共分为三个步骤,如下图:
1、定义需获取的数据的日期
2、删除table_target表中已有数据,注意一定要将“执行SQl语句”面板中的“变量替换”要选上,否则SQL语句中的变量不会被替换,我刚开始没注意到这个地方,找问题找了半天。

3、获取table_source中的数据,并将其插入table_target表
3-1、获取table_source表的数据
3-2、值映射
3-3、字段选择
3-4、对t_id字段进行处理,增加了pointnumber字段。

在这一步骤中发现kettle的一个bug,就是不能在JavaScript中使用str2date函数,错误的具体信息参见:/browse/PDI-1827。

这个问题也折腾了好长时间,刚开始怎么也想不通这个函数使用时怎么会报错呢,后来只好从字符串中截取年、月、日信息。

该步骤中还存在另外一个使人困惑的问题,就是点击“测试脚本”按钮,会报错,但是执行job和transformation时则不会报错。

3-5、增加pointnumber字段至输出结果中
3-6、插入数据至table_target表
3-4步骤中的JavaScript代码如下:
var pointTimeStr = pointtime.getString(); var pointnumber = 1;
if (pointTimeStr == "00:00") {
var marketDateStr = marketdate.getString();
var marketDateYear = substr(marketDateStr, 0, 4);
var marketDateMonth = str2num(substr(marketDateStr, 5, 2))-1; var marketDateDay = substr(marketDateStr, 8, 2);
var date = new Date();
date.setYear(marketDateYear);
date.setMonth(marketDateMonth);
date.setDate(marketDateDay);
var temp1 = dateAdd(date, "d", -1);
marketdate.setValue(date2str(temp1, "yyyy-MM-dd"));
pointtime.setValue("24:00");
pointnumber = 1440;
} else {
var hourStr = pointTimeStr.substr(0, 2);
var hour = str2num(hourStr);
var minuteStr = pointTimeStr.substr(3, 5);
var minute = str2num(minuteStr);
pointnumber = hour * 60 + minute;
}
至此,整个转换工作完成,小结一下:
如果对kettle等etl工具比较熟悉的话,使用etl工具进行数据转换、抽取等事情还是比较方便的,比起写程序还是有优势的。

但是这个转换过程中遇到的kettle的两个bug比较让人头疼,觉得kettle好像还不是很稳定。

相关主题