Heycm

Heycm

Kettel简单使用

875
2022-07-02

Kettel 简介

kettel 是一种 ETL(Extract-Transform-Load的缩写,即数据抽取、转换、装载的过程)工具,对于开发和运维,经常需要处理、转换、迁移各种数据,不同类型的数据库之间、数据库对文件、关系数据库对非关系数据库,如果写程序来处理,相对来说一是比较麻烦,二是效率不高,Kettel 就是专门处理这些问题的。

Kettle(现在已经更名为PDI,Pentaho Data Integration-Pentaho数据集成)。更多介绍请看这里

简单使用

Kettel是开源的ETL工具,纯Java编写,绿色免安装,需要依赖系统Java环境。
这里既是简单使用,只介绍库对库数据迁移转换的一些步骤和常用组件、方法,更多玩法需要自行学习。

安装依赖

数据库连接驱动

下载解压后,Kettle 目录下有一个lib文件夹,新鲜出炉的Kettel没带有各数据库连接驱动,我们需要自行下载连接驱动丢到这个目录下,然后重启kettel就行。

工具包

另外,处理数据时可能会需要对特殊数据做特殊处理,这里还可以把自己项目中一些工具jar包丢进去,在转换数据时直接调用已写好的方法,非常方便。

启动

直接运行 Kettel 目录下的 Spoon.bat 就行

案例

这里以一个案例过程,来展现数据处理的一个简单的流程。

前提条件

既然是数据处理,那前提既是需要有数据,这里我准备了两个库,演示从 origintarget 的数据处理过程。
image-1656743696984


需要说明的是,这里的数据有80多万行,这个数据库是我本地虚拟机用Docker跑的一个库

image-1656743909816
image-1656744012636

image-1656824936915

处理过程

1.根据 col2 的值,生成一个新的列 col5,值为 正数 负数 0
2.使用自己的工具包,对 col3 做脱敏处理,保留前后 2 个字符
3.使用自己的工具包,对 col4 做MD5加密处理
使用以下两个工具类

package online.heycm.tools.cipher.core;

import cn.hutool.crypto.digest.MD5;

public class MD5Core {

    private MD5Core() {}

    /**
     * 加密
     *
     * @param content 加密内容
     * @param salt    盐
     * @return 密文
     */
    public static String encrypt(String content, String salt) {
        MD5 md5 = new MD5(salt.getBytes(), 1024);
        return md5.digestHex(content);
    }

    /**
     * 加密
     *
     * @param content 加密内容
     * @return 密文
     */
    public static String encrypt(String content) {
        MD5 md5 = new MD5();
        md5.setDigestCount(1024);
        return md5.digestHex(content);
    }

}

package online.heycm.tools;

public class SensitiveUtil {

    private static final char STR = '*';

    private SensitiveUtil() {}

    /**
     * 字符串脱敏
     *
     * @param content 原字符串
     * @param left    左边保留字符个数
     * @param right   右边保留字符个数
     * @return
     */
    public static String hidden(String content, int left, int right) {
        assert content != null && left >= 0 && right >= 0;
        String[] split = content.split("");
        StringBuilder builder = new StringBuilder();
        int length = split.length;
        if (length <= (left + right)) {
            for (String s : split) {
                builder.append(STR);
            }
            return builder.toString();
        }
        int strLength = length - right;
        for (int i = 0; i < left; i++) {
            builder.append(split[i]);
        }
        for (int i = left; i < strLength; i++) {
            builder.append(STR);
        }
        for (int i = strLength; i < length; i++) {
            builder.append(split[i]);
        }
        return builder.toString();
    }
}

工具包放到 lib 目录下,重启

image-1656828284037



新建转换

启动 Kettel 后,界面是这样式的
image

直接双击 主对象树 中的 转换,或者从文件新建一个转换也可以,完成后会切换到核心对象树
image-1656739563790

我们再把它切回 主对象树 ,添加 DB 连接,把相关库都给添加上。
image-1656740335835

各项目都写好写完整,数据库类型啥库就啥库,连接方式一般我们都是 lib 目录安装的JDBC驱动jar包,选JDBC就好。
tips:可以稍微保存一下,以免关闭了无法恢复。

测试连接异常

这种情况一般都是各项目没有填写完整,IP、端口、数据库、用户名、密码、防火墙没配置好,没有在 lib 目录下安装相应连接驱动或者驱动不对。

输入

切换到核心对象树,在输入一栏把表输入拉过来,选择源库,获取输入SQL,选择表,生成查询SQL(建议选择生成所有列名,不想要的列可以去掉),预览一下数据,没什么问题就确定。

image-1656829632381

转换

在核心对象树的 转换 一栏中,有很多现成的转换方法可以直接拿来用,如果不能满足自己的转换规则时,可以通过插入脚本的方式实现自定义规则。当然,插入执行脚本也都可以实现转换栏目中的各种转换方法,算是一个兜底的解决方式。

这里以插入Java代码为例,在 脚本 一栏拉出来一个 Java 代码 ,按住 Shift 点击表输入拉出一条指针指向 Java代码 ,这代表着数据的流向。
image-1656830816129

Main 方法拽过来,编写Java脚本
这里删减了一些代码和注释,可以稍微看一下原注释,了解这个方法该怎么写。

image-1656832828432

代码如下

import online.heycm.tools.SensitiveUtil;
import online.heycm.tools.cipher.core.MD5Core;

public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {

    // 当前行
    Object[] r = getRow();

    if (r == null) {
        setOutputDone();
        return false;
    }

    // It is always safest to call createOutputRow() to ensure that your output row's Object[] is large
    // enough to handle any new fields you are creating in this step.
    r = createOutputRow(r, data.outputRowMeta.size());

    // 根据 col2 的值生成 col5
    Long col2 = get(Fields.In, "col2").getLong(r);
    String col5 = "";
    if (col2 > 0) {
        col5 = "正数";
    } else if (col2 < 0) {
        col5 = "负数";
    } else {
        col5 = "0";
    }
    // 脱敏 col3
    String col3 = get(Fields.In, "col3").getString(r);
    col3 = SensitiveUtil.hidden(col3, 2, 2);
    // 加密 col4
    String col4 = get(Fields.In, "col4").getString(r);
    col4 = MD5Core.encrypt(col4);

    // 输出到各字段
    get(Fields.Out, "col3").setValue(r, col3);
    get(Fields.Out, "col4").setValue(r, col4);
    get(Fields.Out, "col5").setValue(r, col5);

    // Send the row on to the next step.
    putRow(data.outputRowMeta, r);

    return true;
}


输出

在输出一栏把表输出拽过来,从Java代码拉出一条指针指向表输出

image-1656833507398

编辑表输出
1.选择目的库
2.选择目标表(如果已经创建好表,直接选择就行,如果没有创建表,可以直接写表名在这里,然后在第6步执行建表SQL);提交数据表示批量提交数量
3.勾选指定数据库字段
4.获取字段(如果输入输出字段不一致,可以自己定义输入字段映射)
5.观察字段映射是否正确
6.SQL可以帮助建表(谨慎使用!!注意观察生成的SQL,如果事先已经创建表,会走Drop)

image-1656833734224

因为我的目标表还没有创建,直接执行这个SQL了

image-1656834247084


启动

配置完成后,点击启动,执行转换。

image-1656834706306

转换过程会输出一些日志和指标,如果发生异常就看日志,一切正常可以看看指标体现性能,当然,转换性能影响参数较多,与处理器、内存、硬盘、网络、数据库软件等息息相关。
下面是转换过程一些截图

开始

image-1656835237901

20万

image-1656835287098

30万

image-1656835331865

完成,用了 5分钟36秒,不算快

image-1656835566124

结果

效果如下

image-1656835777691

image-1656835807118


其他

kettel 将空字符串当null值处理

找到配置文件:C:\Users\用户名.kettle目录中找到kettle.properties
添加配置:KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL=Y
重启kettle

kettel 转换中文乱码

编码问题,编辑器打开Spoon.bat,找到

if "%PENTAHO_DI_JAVA_OPTIONS%"=="" set PENTAHO_DI_JAVA_OPTIONS="-Xms1024m" "-Xmx2048m" "-XX:MaxPermSize=256m"

行末跟着加上 "-Dfile.encoding=UTF-8" 就可以了




附录

Kettel中文站点:http://www.kettle.org.cn/

PDI下载地址:https://sourceforge.net/projects/pentaho/files/

MySQL连接驱动:https://dev.mysql.com/downloads/connector/j/

MariaDB连接驱动:https://downloads.mariadb.com/Connectors/java/

连接驱动从本地 Maven 仓库拿也可以的。