kettle实操笔记


kettle实操笔记


kettle是非常老牌的etl工具了,最早可以追溯到我还未工作的时候,但是不得不说,这个工具非常好用,而且学习成本也比较低,所以现在很多实际的项目中仍然有不小的使用率,也正是因为如此,我就把入门级别的一个实操笔记分享给大家,有很多深入的使用大家还是得到网上去检索,比如集群、比如接口等等。

基本操作

几个基础概念

etl

ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库,但其对象并不限于数据仓库。

ETL是将业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程,目的是将企业中的分散、零乱、标准不统一的数据整合到一起,为企业的决策提供分析依据, ETL是BI(商业智能)项目重要的一个环节

简单一句话就是etl就是数据交换的工具。可以提供跨数据库数据交换,支持定时任务,支持多种数据格式,支持数据治理等等。

转换

转换是kettle中的一个对象,是数据交换的基础对象。

kettle实操笔记
image-20211110164219383
输入对象

主要是数据源的输入对象,例如:表输入。

kettle实操笔记
image-20211110164250799

几点注意

  • 表输入对象中,需要选择数据连接
  • sql尽量在plsql中先测试并编辑好,尽量不要使用获取sql
  • 增量交换尽量限制记录数,如果记录数设置为0,则是将sql查出的全部结果集作为输入
kettle实操笔记
image-20211110164908525
输出对象

作为数据交换后的数据输出,例如:表输出。

kettle实操笔记
image-20211110164307732

几点注意

  • 表输出中需要选择数据库连接,即数据最终要推送的目标数据源 目标模式:在oracle作为表输出的数据源时,需要明确目标模式
  • 目标表:对应输出表的表名
  • 提交记录数量:最大作为一批次向目标数据源commit的数据记录限制,需要根据实际情况设置,比如如果单批次10000数据的时间必须一致(时间戳模式),那么此处应设置为10000
  • 指定数据字段:需要做字段映射关系设置时应选择(一般都需要)
  • 获取字段:根据表输入和表输出的字段生成初始映射关系
  • 输入字段映射:需要对字段映射关系做调整时使用,比如部分字段不推送
kettle实操笔记
image-20211110165059927
kettle实操笔记
image-20211110165542780
脚本对象

可以直接在其中进行脚本编写,以实现满足业务需要的数据处理,如:sql脚本,可以直接在其中编写标准的sql。

kettle实操笔记
image-20211110164327119
转换对象

需要对输入的数据进行处理,比如去重,值映射等。

kettle实操笔记
image-20211110164344397
数据连接
kettle实操笔记
image-20211110164451622

几点注意:

当数据库连接是oracle,并且版本大于12时,需要选择oracle RDB方式,并且对应的数据库连接信息需要在kettle的jdbc配置文件(kettledata-integrationsimple-jndijdbc.properties)中进行配置,而在设置数据库连接时只需要输入对应定义的JNDI名称即可

kettle实操笔记
image-20211110165823983
kettle实操笔记
image-20211110170114169

作业

作业是对转换的组合、调度,在转换中是没有严格意义的先后顺序的,而作业中的每一个任务环节都是有顺序的。

比如,在转换中,表输入1万条数据,而表输出是按照1千条记录条件,那么在提交了1千条之后,表输出之后的任务也会同步开始,而不是等1万条都输出完成

kettle实操笔记
image-20211110170525313

如上图中,作业的执行顺序是start->truncateXXX->同步->转换->成功,任何一个环节异常都会导致作业失败。

作业中的常用对象包括START(标记任务开始),脚本对象(与转换的脚本对象类似),转换对象(可以选择定义好的转换对象),成功(标记正常结束)

START

可以定义任务的执行周期,也就是起到定时器的作用。可以按照秒、分钟、小时、天、周、月的周期进行配置。

kettle实操笔记
image-20211110170813813
启动

选择日志类型,在测试时可以选择基本日志,在正常启用后建议把日志设置为错误日志级别,也就是有异常时才会记录,主要可以大大提升kettle的运行稳定性,因为日志会在控制台输出,而长时间的输出会导致内存溢出等异常。

kettle实操笔记
image-20211110171108582

进阶场景实操

以上都是入门的操作,也很简单,但是实际我们在数据处理和交换时往往会遇到比较复杂的情况,因此根据场景进行组合、定制才是关键。

首先要说的一点是,kettle的目的是进行数据交换,因此我们在开始定制前应该先把数据交换的逻辑整理清楚,然后在按照逻辑去定制,这样才能保证没有问题,也就是说kettle使用是需要一定的设计能力的。

另外一点需要说的是,kettle在做数据交换时定制很方便,但是如何提高kettle的稳定性和交换性能是需要去注意的。

场景一 增量交换

增量交换是经常会遇到的一个场景,应该说是基础中的基础场景,大部分的数据交换都是需要满足长期的增量交换的,复杂的交换任务其实都是基于增量交换的逻辑去处理的。

增量交换常用的几种方式,时间戳、标记位、推送记录。个人比较喜欢用的是推送记录方式

时间戳方式

首先要在待交换的数据中统一时间戳数据项,同时要将每次交换完成的最大时间戳记录,要保证在每次抽取时将满足的数据全部抽取

此种方式存在几个问题:

  • 需要限制每次的数据量大小,因为数据量过大影响交换效率和数据准确性,对于无法保证某一时间交换数据量的情况下,不建议使用该方式。
  • 可能存在数据并发时,导致漏数据的情况

标记位

标记位是指在待交换数据项中,其中一项作为标记为数据项,在交换完成时需要修改该数据项为已交换,而每次抽取时只读取未标记的数据

此种方式存在几个问题:

  • 需要修改数据源的数据,因此会大大降低交换的效率。对于数据量较大的情况,不建议采用。

推送记录

顾名思义,就是将已推送的数据进行记录,再次推送时只推送不在记录中的数据。

此种方式存在几个问题:

  • 需要额外创建交换记录表,而且需要包含待交换数据的主键数据项
  • 历史交换记录随着交换的增加而剧增,后期会影响交换性能(优化方式:需要定期做历史数据备份,以此来优化交换效率)

例子就是一个推送记录的方式进行的数据交换

kettle实操笔记
image-20211110175239116

上图的转换定义了在数据集输入(oracle)后,首先为数据集生成UUID,然后插入记录表,最后交换至mysql的目标库。

场景二 内部循环

比如这个场景,我们需要删除1千万的数据,简单的任务,我们可以直接定制一个脚本,在其中写入需要删除数据的逻辑即可

但是实际生产环境中,删除1千万的数据会需要很长时间,如果是一个并发读写的数据表时间就会更长,很有可能最后导致删除失败任务卡死,或者表被锁死。

解决思路

一次性删除1千万很慢,但是删除几万数据还是很快的,所以需要将1千万的数据分批次删除,这个时候就需要去使用内部循环,在目标数据未删除之前,需要一直重复运行删除操作。

kettle实操笔记
image-20211110204728084

详细任务配置

basic_num是计算待删除数量的转换,将数量作为参数传递给下一步骤,下一步骤采用验证组件

kettle实操笔记
image-20211110205104398
kettle实操笔记
image-20211110205150802
kettle实操笔记
image-20211110205229519

设置在父作业中变量生效,即可将变量的值传给作业,进而在下一步骤的组件中获取到

kettle实操笔记
image-20211110205419352

场景三 kettle的函数

有时候我们需要使用kettle给我们提供的内置函数带来应用中的一些方便。比如日期函数

如下的一个应用中,我们需要获取执行任务的当前时间,以避免与数据库的时间不一致导致与预期的时间影响不一致。

kettle实操笔记
image-20211110210338785

具体看下该转换

kettle实操笔记
image-20211110210815611

获取系统信息

kettle实操笔记
image-20211110210851112

有很多的系统函数,可以自行去尝试一下,这里获取系统日期和时间,并把它赋值给DQ_DATE参数,再看下格式化的js代码

//Script here

Date.prototype.Format = function (fmt//author: meizz 
    var o = {
        "M+"this.getMonth() + 1//月份 
        "d+"this.getDate(), //日 
        "h+"this.getHours(), //小时 
        "m+"this.getMinutes(), //分 
        "s+"this.getSeconds(), //秒 
        "q+"Math.floor((this.getMonth() + 3) / 3), //季度 
        "S"this.getMilliseconds() //毫秒 
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}
 
var dtNew=new Date(new Date().getTime()).Format("yyyy/MM/dd/ hh:mm:ss");

设置变量刚才已经介绍过了,同样是设置在父作业中生效

kettle实操笔记
image-20211111104226358

在父作业中,需要设置下一步骤的转换参数信息

kettle实操笔记
image-20211111104358627

在该转换内部需要设置读取变量

kettle实操笔记
image-20211111105257319

在转换中的步骤中可以直接使用该变量

kettle实操笔记
image-20211111105355206

补充:

格式化的另一种方式,比js代码更方便,就是使用字段选择组件,在其中设置格式化即可。

kettle实操笔记
image-20211111105552554

kettle的集群

这部分大家在充分掌握以上内容之后,再去研究。kettle的集群很厉害

另外,还有其他的一些比较新的工作,比如DataX,这个也是性能很好的工具,推荐大家去掌握。

注意点:

对数据库比较熟悉的同学,尽量利用数据库的能力来满足交换,这样可以在对kettle没有那么熟的时候满足大部分的交换场景,因为kettle作为etl工具,他对交换的最大瓶颈一定来自于数据库的IO能力。对于初学者,我也建议先熟悉数据库相关的技术知识

常见问题

  • 尽量不要使用插入更新作为输出,因为效率太低,尽量使用表输出,而且输出的表尽量是空表,这样效率最高
  • 有时候会出现kettle工具内存不够报错的情况,可以在启动的脚本中设置大一点的Xms(JVM的初始堆内存)和Xmx(JVM的最大堆内存),java.lang.OutOfMemory错误就是Xmx的值过低导致,但是一般将这两个值设置为一样大,也就是物理内存的1/4,这么做是避免GC之后调整堆大小;另外MaxPermSize是最大非堆内存的,这个值一般为物理内存的1/4,如果过小会报内存溢出(java.lang.OutOfMemoryError: PermGen space),但是要注意Xmx和MaxPermSize的总和不能超过物理内存,否则无法启动,这些其实是JVM的知识,对于java的应用程序都是通用的。


原文始发于微信公众号(云户):kettle实操笔记

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/35239.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!