CategoryResourceRepost/极客时间专栏/SQL必知必会/第四章:SQL项目实战/46丨数据集成:如何对各种数据库进行集成和转换?.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

188 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="46丨数据集成如何对各种数据库进行集成和转换" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/95/fe/95d30b17540e66799bdb3379f9a205fe.mp3"></audio>
我们的数据可能分散在不同的数据源中如果想要对这些数据分析就需要先对这些数据进行集成。同时因为不同的来源这些数据可能会存在各种问题比如这些数据源采用了不同的DBMS数据之间存在冗余的情况比如某一条数据在不同的数据源中都有记录那么在数据集成中我们只保留其中的一条就可以了。除此以外这些不同的数据源还可能字段标识不统一再或者我们需要将数据转换成我们想要的格式要求进行输出。
数据集成是数据分析之前非常重要的工作,它将不同来源、不同规范以及不同质量的数据进行统一收集和整理,为后续数据分析提供统一的数据源。
好了,关于这部分内容,今天我们一起来学习下:
1. 我们将数据从OLTP系统中转换加载到OLAP数据仓库中这中间重要的步骤就是ETL。那什么是ETL呢
1. 认识Kettle工具。在Kettle中有两个重要的脚本分别是Transformation转换和Job作业它们分别代表什么
1. 完成两个实例项目。通过使用Kettle完成MySQL数据表的数据同步以及根据我们的需求将银行客户转账的记录导出到目标文件中。
## 什么是ETL
在使用数据的时候根据需求我们可以分成OLTP和OLAP两种场景。OLTP更注重数据的实时性而OLAP更注重数据的分析能力对时效性要求不高。在这个过程中我们的数据源来自于OLTP系统而最终得到的数据仓库则应用在OLAP系统中中间的转换过程就是ETL如下图所示
<img src="https://static001.geekbang.org/resource/image/7d/42/7d8ee4be2192b2c87d3e997e184c4542.jpg" alt=""><br>
ETL是英文Extract、Transform和Load的缩写也就是将数据从不同的数据源进行抽取然后通过交互转换最终加载到目的地的过程。
在Extract数据抽取这个过程中需要做大量的工作我们需要了解企业分散在不同地方的数据源都采用了哪种DBMS还需要了解这些数据源存放的数据结构等是结构化数据还是非结构化数据。在抽取中我们也可以采用全量抽取和增量抽取两种方式。相比于全量抽取增量抽取使用得更为广泛它可以帮我们动态捕捉数据源的数据变化并进行同步更新。
在Transform数据转换的过程中我们可以使用一些数据转换的组件比如说数据字段的映射、数据清洗、数据验证和数据过滤等这些模块可以像是在流水线上进行作业一样帮我们完成各种数据转换的需求从而将不同质量不同规范的数据进行统一。
在Load数据加载的过程中我们可以将转换之后的数据加载到目的地如果目标是RDBMS我们可以直接通过SQL进行加载或者使用批量加载的方式进行加载。
## 认识Kettle工具
Kettle可以帮助我们完成ETL工作它的设计师希望它能像水壶一样可以从将不同的数据通过Kettle水壶按照指定的格式流出来。
相比于其他商业软件来说Kettle是Java开发的免费开源工具可以运行在多个操作系统中。因此在使用之前你需要安装Java运行环境JRE。Kettle的[下载地址](https://community.hitachivantara.com/docs/DOC-1009855)在这里。
在Kettle中有3个重要的组件
1. Spoon勺子它是一个图形界面帮我们启动作业和转换设计。
1. Pan通过命令行方式完成转换执行Transformation
1. Kitchen厨房通过命令行方式完成作业执行Job
通过Spoon我们可以采用可视化的方式对Kettle中的两种脚本进行操作这两种脚本分别是Transformation转换和 Job作业
Transformation转换对应的是.ktr文件它相当于一个容器对数据操作进行了定义。数据操作就是数据从输入到输出的一个过程Tranformation可以帮我们完成数据的基础转换。
Job作业对应的是.kjb文件Job帮我们完成整个工作流的控制。相比于Transformation来说它是个更大的容器负责将Transformation组织起来完成某项作业。
你可以把Transformation理解成比Job粒度更小的容器。在通常的工作中我们会把任务分解成为不同的Job然后再把Job分解成多个Transformation。
## Kettle使用实例
我们刚才对Kettle有了大致的了解Kettle工具包含的内容非常多下面我们通过两个实例更深入地了解一下。
### 实例1将test1数据库中的heros数据表同步到test2数据库中
**数据准备:**
首先我们在MySQL中创建好test1和test2两个数据库在test1中存储了我们之前已有的heros数据表包括表结构和表数据然后在test2数据库中同样保存一个heros数据表注意test2数据库中只需要有heros表结构即可。数据同步是需要我们使用Kettle工具来完成的。
你可以[点击这里](https://github.com/cystanford/SQL-Kettle/blob/master/heros.sql)下载heros数据表结构及数据。
下面我们来使用Kettle来完成这个工作只需要3步即可。
**第一步创建表输入组件并对test1数据库中的heros数据表进行查询。**
在Kettle左侧的面板中找到“核心对象”输入“表输入”找到表输入组件然后拖拽到中间的工作区。
双击表输入选择Wizard来对数据库连接进行配置。这里我们可以创建一个数据库连接test1然后选择MySQL。然后输入我们的服务器主机地址以及数据库名称最后输入MySQL的用户名和密码完成数据库连接的创建工作。
<img src="https://static001.geekbang.org/resource/image/92/44/92b0c458667f6c3db6a7c49409a25844.png" alt=""><br>
创建好连接之后我们来对heros数据表进行查询输入SQL语句SELECT * FROM heros你也可以通过获取SQL查询语句的功能自动选择想要查询的字段。
然后点击确定完成表输入组件的创建。
**第二步,创建插入/更新组件配置test2数据库中的heros数据表的更新字段。**
如果我们想要对目标表进行插入或者更新,这里需要使用“插入/更新”组件。我们在Kettle左侧的面板中找到这个组件然后将它拖拽到中间的工作区。
在配置“插入/更新”组件之前,我们先创建一个从“表输入”到“插入/更新”的连接这里可以将鼠标移动到“表输入”控件上然后按住Shift键用鼠标从“表输入”拉一个箭头到“插入更新”。这样我们就可以在“插入/更新”组件中看到表输入的数据了。
<img src="https://static001.geekbang.org/resource/image/23/af/2392155c3e0a5aa8cafb872e5ab14eaf.png" alt=""><br>
然后我们对“插入/更新”组件进行配置双击该组件这里同样需要先创建数据库连接test2来完成对数据库test2的连接原理与创建数据库连接test1一样。
接着我们选择目标表这里点击浏览按钮在test2连接中找到我们的数据表heros选中并确定。
<img src="https://static001.geekbang.org/resource/image/e9/eb/e97761f5be696453a897f88803723beb.png" alt=""><br>
然后我们可以在下面指定查询关键字这里指定表字段为id比较符为=数据流里的字段1为id这样我们就可以通过id来进行查询关联。
然后对于目的表中缺失的数据,我们需要对相应的字段进行更新(插入),这里可以直接通过“获取和更新字段”来完成全部更新字段的自动获取。
<img src="https://static001.geekbang.org/resource/image/c6/f7/c669c77dbd993e5d10c0ba96a5f288f7.png" alt=""><br>
然后点击“确定”完成“插入/更新”组件的创建。
**第三步,点击启动,开始执行转换。**
这时Kettle就会自动根据数据流中的组件顺序来完成相应的转换我们可以在MySQL中的test2数据库中看到更新的heros数据表。
<img src="https://static001.geekbang.org/resource/image/73/d4/7362b4c7c51026d99ce089c92889edd4.png" alt=""><br>
我将转换保存为test1.ktr 上传到了[GitHub](https://github.com/cystanford/SQL-Kettle)上,你可以下载一下。
## 实例2导入用户交易流水
刚才我们完成了一个简单的Kettle使用实例现在我们来做一个稍微复杂一些的数据转换。
首先准备数据库。在数据库创建account和trade两张表。其中account表为客户表字段含义如下
<img src="https://static001.geekbang.org/resource/image/cb/ca/cb64830c0f832242f4f3ed3420a791ca.png" alt=""><br>
trade表为客户交易表字段含义如下
<img src="https://static001.geekbang.org/resource/image/f1/68/f11cdfc9e83d124c9a07555f76862268.png" alt=""><br>
你可以[点击这里](https://github.com/cystanford/SQL-Kettle)下载account和trade数据表结构及数据下载。
现在我们希望将客户的交易流水导入到txt文件中输出内容包括4个字段account_id1、account_id2、amount和value。其中value为新增的字段表示转账的类型当转账对象account_id2为个人账户则输出“对私客户发生的交易”为公司账户时则输出“对公客户发生的交易”。
实际上我们在模拟从多个数据源中导出我们想要的数据,针对这个例子,我们想要输出的数据内容为打款账户,收款账户,转账金额,以及交易类型。
下面我们来看下如何使用Kettle来完成这个工作。
**第一步创建表输入组件并对数据库中的trade数据表进行查询。**
这里我们创建数据库连接然后在SQL查询中输入SELECT * FROM trade相当于对trade进行全量获取。
**第二步创建数据库查询对account表进行查询。**
在Kettle左侧面板找到“数据库查询”控件拖拽到中间的工作区命名为“account表查询”然后将“表输入”控件和“account表查询”之间进行连接。这样我们就可以得到“表输入”控件中的数据流。
然后我们对“account表查询”控件进行配置这里我们需要连接上account数据表然后对account数据表中的account_id与trade数据表中的account_id2进行关联查询返回值设置为customer_type。
<img src="https://static001.geekbang.org/resource/image/45/2c/4574b9897615b7d67b19c0f415f1992c.png" alt=""><br>
这样我们可以通过account数据表得到trade.account_id2所对应的customer_type。也就是收款账户的账户类型个人/公司)。
**第三步创建过滤记录对不同的customer_type进行类型修改。**
我们需要根据收款账户的类型来进行交易类型的判断因此这里我们可以根据前面得到的customer_type来进行记录的过滤。
这里在Kettle左侧的面板选择“过滤记录”拖拽到中间的工作区然后创建从“account表查询”到“过滤记录”的连接。
在“过滤记录”中我们设置判断条件为customer_type = 1。
<img src="https://static001.geekbang.org/resource/image/a5/47/a5682bae98f0adb29507efc4d68ebd47.png" alt=""><br>
然后在从Kettle左侧面板中拖拽两个“JavaScript代码”控件到工作区分别将步骤名称设置为“对公类型修改”和“对私类型修改”
然后在对应的Script脚本处设置变量customer_type_cn。
<img src="https://static001.geekbang.org/resource/image/ef/cc/ef78804fa6698712cdb286f028a2f6cc.png" alt="">
<img src="https://static001.geekbang.org/resource/image/d2/61/d2f6be25c63aceb1aea9f04dc94eb361.png" alt=""><br>
然后我们在Kettle左侧面板拖拽两个“增加常量”控件到中间的工作区分别命名为“增加对公常量”和“增加对私常量”。然后将刚才的设置的两个“Javascript代码”控件与“增加常量”控件进行连接。
在增加常量控件中,我们可以设置输出的常量:
<img src="https://static001.geekbang.org/resource/image/bd/1a/bd820ef009d740854034771d69d0211a.png" alt="">
<img src="https://static001.geekbang.org/resource/image/b5/3a/b5c69f9cf550c02a43bce694f056443a.png" alt=""><br>
这样我们就可以把得到的常量在后面结果中进行输出。
**第四步,创建文本文件输出,将数据表导入到文件中。**
刚才我们已经设置了从trade数据表中进行查询然后通过account表关联查询得到customer_type然后再根据customer_type来判断输出的常量是对公客户发生的交易还是对私客户发生的交易。这里如果我们想要导入到一个文本文件中可以从Kettle左侧面板中拖拽相应的控件到中间的工作区。然后将刚才设置的两个控件“增加对公常量”和“增加对私常量”设置连接到“文本文件输出”控件中。
然后在“文本文件输出”控件中找到字段选项设置我们想要导入的字段你可以通过“获取字段”来帮你辅助完成这个操作。这里我们选择了account_id1、account_id2、amount以及刚才配置的常量value。
<img src="https://static001.geekbang.org/resource/image/b9/8b/b91d81cba3663ed5d5a7049da3cb6e8b.png" alt=""><br>
然后我们点击确定就完成了所有配置工作,如下图所示。
<img src="https://static001.geekbang.org/resource/image/1f/b5/1ffac59cd97629aaf8734a45dad3f8b5.png" alt=""><br>
当我们开启转换后,整个数据流就会从表输入开始自动完成转换和判断操作。将其导入到我们的文本文件中,导出的结果如下:
```
account_id1;account_id2;amout;value
322202020312335;622202020312337;200.0;对私客户发生的交易
322202020312335;322202020312336;100.0;对公客户发生的交易
622202020312336;322202020312337;300.0;对公客户发生的交易
622202020312337;322202020312335;400.0;对公客户发生的交易
```
我将上述过程的转换保存为test2.ktr 上传到了[GitHub](https://github.com/cystanford/SQL-Kettle)上,你可以下载看一下。
## 总结
今天我们讲解了数据集成的作用以及ETL的原理。在实际工作中因为数据源可能是不同的DBMS因此我们往往会使用第三方工具来帮我们完成数据集成的工作Kettle作为免费开源的工作在ETL工作中被经常使用到。它支持多种RDBMS和非关系型数据库比如MySQL、Oracle、SQLServer、DB2、PostgreSQL、MongoDB等。不仅如此Kettle易于配置和使用通过可视化界面我们可以设置好想要进行转换的数据源并且还可以通过JOB作业进行定时这样就可以按照每周每日等频率进行数据集成。
<img src="https://static001.geekbang.org/resource/image/4b/c4/4b004a7fa2adea85131654e7766937c4.png" alt=""><br>
通过今天的两个Kettle实例相信你对Kettle使用有一定的了解你之前都用过哪些ETL工具不妨说说你的经历
第二个实例中我们将交易类型分成了“对公客户发生的交易”以及“对私客户发生的交易”。如果我们的需求是分成4种交易类型包括“公对公交易”、“公对私交易”、“私对公交易”以及“私对私交易”那么该如何使用Kettle完成这个转换呢
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。