暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kettle知识库问答系列之零零后浪

以数据之名 2022-04-27
241


1 、背景 摘要

  • 微信公众号、知乎稀土掘金,主体均为以数据之名”
  • 欢迎扫码关注,回复「666」加入以数据之名”微信交流群
  • 本文由以数据之名分享,正所谓“道阻且长,行则将至;行而不辍,未来可期”。不知不觉中,“以数据之名”Kettle解忧消愁系列专题已更新了七篇知识库文章“三十而立四十不惑、五十而耳知天命、六十而耳顺、七十古稀、八零年代、九零新秀”,叙述了使用Kettle作为ETL开发的常见组件使用说明、业务场景实现逻辑、异常分析及组件性能优化相关内容。今天,我们跟着小编的节奏,继续探讨第八篇Kettle知识库问答系列之零零后浪,做到理念和实践的生动统一。

2 、Kettle 组件 探索

2.1 第91问

问:Kettle组件数据库查询数据库连接,都能实现根据主表关键字查询子表数据,有什么差别呢?  


答:我们可以从以下7个角度来对比两者的异同

1、Join模式:

数据库查询:根据查询关键字条件。勾选如下条件则,等同于inner join;不勾选,默认是left join。

数据库连接:有如下条件控制join模式。勾选,等同于left join;不勾选,等同于数据库的inner join。(优)

2、返回记录数:

数据库查询:根据查询关键字条件,只会返回第一条,但多条可通过排序配置控制返回那一条;

数据库连接:有如下条件控制返回条数;0:代表全部返回,其他数字代表返回几条。配合join模式条件组合使用。(优)

3、缓存支持:

数据库查询:缓存使用控制和大小控制;针对于代码表、标签表等小表信息,可采用改配置一次性加载到缓存,减少数据库访问;(优)

数据库连接:不支持。

4、查询异常控制:

数据库查询:查不到的异常控制;查询到多行任务失败;

数据库连接:不支持,一般场景不需要该配置职称。

5、查询数据库次数:

数据库查询:配合缓存,可一次或一条一次;(优)

数据库连接:一条流一次。

6、 个性化程度:

数据库查询:更局限,只支持数据流字段固定配置;

数据库连接:更个性化(SQL配置,条件和字段可操作性更高),可以支撑字段或条件使用数据库函数;(优)

7、参数支持:

数据库查询:不支持;

数据库连接:支持全局动态参数使用${param_name}或'${param_name}'。(优)


2.2 第92问

问:Kettle JavaScript脚本组件如何做多字段比较呢?

答:这种场景对于经常使用JS的同学来说,很常见。比如,我们需要根据前面数据流的输入字段比较结果,判断新增一个路由字段的值。

既然要做js比较,那我们先看一张js运算比较参考表:

运算符

描述

比较

返回

==

等于

x == 8

false

x == 5

true

x == "5"

true

===

值相等并且类型相等

x === 5

true

x === "5"

false

!=

不相等

x != 8

true

!==

值不相等或类型不相等

x !== 5

false

x !== "5"

true

x !== 8

true

>

大于

x > 8

false

<

小于

x < 8

true

>=

大于或等于

x >= 8

false

<=

小于或等于

x <= 8

true

综上可知:

  • ==(或!=)

1、先检查需要操作两个字段数据类型是否一致?

一致,进行===比较;不一致,则进行一次类型转换,转换为相同的类型再进行比较

  • ===(或!==)

1、直接比较类型,类型不一致就直接false
2、如果俩和值的引用都是同一个对象或是函数,那么相等,否则不相等.
3、对象使用三个等号是用来比较引用的
4、所以才会有那中地址不变,前后就相等,所以才用特殊的方式来处理数组和对象

下面我们用Kettle Js脚本实际使用案例,来对比js比较的使用策略。

1、测试数据集:

2、异常使用场景

验证方案:

异常输出结果:(字段值可能因为隐式转换,导致结果不符合预期,所以需要先强制转换,再进行比较)

3、正常使用场景

验证方案:

正常输出结果:


3 、Kettle MySQL 探索

3.1 第93问

问:Kettle 9.2+mysql 8.0.19  ,报如下异常Unable to get value ‘Date’from database resultset,index 6 (HOUR_OF_DAY:0 -> 1),如何解决呢?  

答:

这种情况一般是输入或输出组件的对应数据库类型的JDBC驱动版本不匹配,比如服务端MySQL 8.0使用了mysql-connector-java-8.0.x.jar的驱动包。推荐使用mysql-connector-java-5.1.48.jar,可以兼容MySQL 5.7和MySQL 8.0

3.2 第94问

问:Kettle SQL实现连续数字或连续递减问题,我们可以以下面的连续数字示例,作为验证场景,看SQL层面如何实现【趣味探讨】?

答:

1、测试表创建:

CREATE TABLE `temp_year` (
`year` int DEFAULT NULL,
`flag` smallint DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

2、数据初始化:

insert into temp_year(`year`,flag) value (2010,1),(2011,1),(2012,1),(2013,0)
,(2014,0),(2015,1),(2016,1),(2017,1),(2018,0),(2019,0);

3、查询SQL:

SELECT 
b.`year`,
b.flag,
(SELECT
COUNT(1)
FROM
temp_year c
WHERE
c.`year` <= b.`year`
AND c.`year` > (SELECT
IFNULL(MAX((d.`year`)), 0)
FROM
temp_year d
WHERE
c.flag != d.flag
AND d.`year` <= b.`year`)) num
FROM
temp_year b

4、查询结果:

select a,b
,ROW_NUMBER() OVER(partition by b,(num-rn) order by num) AS c
from (
select a,b,num
,ROW_NUMBER() OVER(partition by b order by num) AS rn
from (
select a,b,ROW_NUMBER() over( order by a) as num
from (
select 2010 as a,1 as b from dual union all
select 2011 as a,1 as b from dual union all
select 2013 as a,1 as b from dual union all
select 2014 as a,0 as b from dual union all
select 2016 as a,0 as b from dual union all
select 2018 as a,1 as b from dual union all
select 2019 as a,1 as b from dual union all
select 2020 as a,1 as b from dual union all
select 2021 as a,0 as b from dual union all
select 2022 as a,0 as b from dual
) t0
) t1
) t2
order by a


3.3 第95问

问:Kettle SQL 如何实现反向计算某一年某一周的起始日【趣味探讨】?


答:我们以MySQL为例,反向计算某年某一周的周一和周日分别对应日期

SELECT 
DATE_ADD(DATE_SUB(concat(substr('2022 第02周',1,4),'-01-01'),
INTERVAL CASE
WHEN DAYOFWEEK(concat(substr('2022 第02周',1,4),'-01-01')) - 1 = 0 THEN 7
ELSE DAYOFWEEK(concat(substr('2022 第02周',1,4),'-01-01')) - 1
END DAY),
INTERVAL (CONVERT(substr('2022 第02周',7,2), UNSIGNED INTEGER)-1)*7 + 1 DAY) as first_day_of_week,
DATE_ADD(DATE_SUB(concat(substr('2022 第02周',1,4),'-01-01'),
INTERVAL CASE
WHEN DAYOFWEEK(concat(substr('2022 第02周',1,4),'-01-01')) - 1 = 0 THEN 7
ELSE DAYOFWEEK(concat(substr('2022 第02周',1,4),'-01-01')) - 1
END DAY),
INTERVAL (CONVERT(substr('2022 第02周',7,2), UNSIGNED INTEGER)-1)*7 + 7 DAY) as last_day_of_week


4 、Kettle 异常 探索

4.1 第96问

问:Kettle Java脚本组件如何输出Integer类型字段呢 ?或者处理如下Integer使用异常?

Conversion error:

aa Integer : There was a data type error: the data type of java.lang.Integer object [1] does not correspond to value meta [Integer]

答:

很多场景我们需要输出字符型的字段,作为后续数据流的处理路由或路由结果输出,避免隐身转换带来的性能损耗。那我们用下面一个简单示例,来阐述如何输出Integer字段追加到数据流。

1、测试数据集如下:

2、异常使用场景:

这里写会抛出如下异常

3、正常使用场景:

4.2 第97问

问:Kettle 如何实现多源数据模型(如A【a1,a2,update_time】、B【b1,b2,update_time】)更新到同一张目标表模型(C【a1,a2,b1,b2,update_time】)?

答:我们从以下三个步骤来做整体ETL设计:

1、以a为主表,用a表的增量时间戳获取增量数据,然后a join b获取全字段数据,执行插入更新操作,同时记录本批次a的最大时间戳,循环操作;

2、以b为主表,用b表的增量时间戳获取增量数据,然后b join a获取全字段数据,执行插入更新操作,同时记录本批次b的最大时间戳,循环操作;

3、为防止两个ETL并行提交事务冲突,可以串行执行两条链路。

5 、Kettle VS 数据库 组件对比

5.1 第98问

问:Kettle 的group by组件和数据库的group by有区别吗?

答:Kettle层面:分组组件的前面必须按照分组字段保证数据有序,所以必须先排序再分组。简单点说:分组和排序是成对出现的【如果是多分支合并分组,也应该多分支合并排序】  多分支分别排序不能保证分组前数据有序,如下图是错误用法:

数据库层面:分组group by key本身包含排序的逻辑,所以无需配合order by key使用。那么分组的原理如何呢?

  • step_type无索引

  • Extra 这个字段的Using temporary表示在执行分组的时候使用了临时表

  • Extra 这个字段的Using filesort表示使用了排序

group by 的简单执行流程

  1. 创建内存临时表,表里有两个字段step_type和count(1);

  2. 全表扫描tp_c_blood_etl_table的记录,依次取出step_type= 'X'的记录。

  • 判断临时表中是否有为 step_type='X'的行,没有就插入一个记录 (X,1);

  • 如果临时表中有step_type='X'的行的行,就将x 这一行的count(1)值加 1;

  1. 遍历完成后,再根据字段step_type做排序,得到结果集返回给客户端。

group by 的性能隐患

group by使用不当,很容易就会产生慢SQL 问题。因为它既用到临时表,又默认用到排序。有时候还可能用到磁盘临时表。所以建议对group by key的key字段添加索引,可有效提高查询效率

5.2 第99问

问:你来问?

答:我来答。

5.3 第100问

问:你来问

答:我来答。

6 、 Kettle 专题推荐

Kettle插件开发之Splunk篇

Kettle插件开发之Elasticsearch篇

Kettle插件开发之KafkaProducer篇

Kettle插件开发之KafkaConsumer篇

Kettle插件开发之KafkaConsumerAssignPartition篇

Kettle插件开发之MQToSQL篇

Kettle插件开发之Redis篇

基于Kettle快速构建基础数据仓库平台

Kettle知识库问答系列之三十而立

Kettle知识库问答系列之四十不惑

Kettle知识库问答系列之五十而知天命

Kettle知识库问答系列之六十而耳顺

Kettle知识库问答系列之七十古稀

Kettle知识库问答系列之八零年代

Kettle知识库问答系列之九零年代

Kettle实战系列之Carte集群应用

Kettle实战系列之动态邮件

Kettle实战系列之基于Carte构建微服务

Kettle基于Yarn分布式调度引擎容器化

小编心声

虽小编一己之力微弱,但读者众星之光璀璨。小编敞开心扉之门,还望倾囊赐教原创之文,期待之心满于胸怀,感激之情溢于言表。一句话,欢迎联系小编投稿您的原创文章!

让我们携手成为技术专家

欢迎关注,快乐交流,共同成长

参考资料

[1]

mrakdown插件: https://github.com/markdown-it/markdown-it/issues/410

[2]

markdown主题: https://product.mdnice.com/themes

[3]

ES 官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/misc-cluster.html#cluster-shard-limit

[4]

Carte脚本前端封装源码: https://github.com/wbenxin/kettle-carte


文章转载自以数据之名,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论