总体阐述
随着企业信息化建设的发展,大量企业都在架设基于自身所在行业的特点的商业智能系统,来指导商业运营。设计合理,运营高效的商业智能系统,在企业的经营决策中,越来越起着至关重要的作用。
IBM InfoSphere Information Server 作为可扩展的企业信息体系结构基础,可以满足企业对于巨大信息量的需求,使企业在运营中更快的交付使用高质量的业务成果。 IBM Infosphere DataStage 作为它的重要组成部分,支持数据结构从简单到复杂的大量数据进行收集,转换和分发,通过对大量数据进行高性能处理,解决企业基于大规模数据的业务问题。
运行时列扩展(Runtime Column Propagation)是 InfoSphere DataStage 提供的一个增强功能,使得用户定义的作业 (job) 不仅能导入用户在作业中定义的数据字段,还能够运行时动态扩展用户要导入的感兴趣的列,他是在运行时才确定作业需要导入的数据列的一个特性。这提供了一种可能,即不需要修改作业,只需要在运行时改变 schema 文件,就能改变作业要导入的数据内容。
使用这个技术有个前提条件,即所定义的项目要支持运行时列扩展属性。可以在项目的属性窗口增加或者去掉对这一特性的支持。通常数据源的阶段 (stage) 需要指定含有源数据的列定义的文件,称为 schema 文件,这样在运行时,动态更新 schema 文件的内容,datastage 的作业可以运行时动态读取数据源文件的数据。
在 DataStage 8.7 中可以接收 schema 文件的阶段如下。
- Sequential File
- File Set
- Column Import
- Column Export
- External Source
- External Target
本文将首先介绍运行时列扩展项目级支持的设置,以及如何创建 schema 文件。其次将根据多年的商业智能项目经验,虚拟出 RCP 使用的典型场景,一步一步实现 RCP 在 InfoSphere DataStage 中的使用,给出每个细节,包括作业的设计,每个阶段的参数设置,详细介绍 RCP 是如何在 ETL 中复用 DataStage 的作业,提高数据处理作业的质量。
开始使用 RCP
项目级别设置支持 RCP
打开 administrator client, 打开登录界面如下图 1 所示,输入安装了 InfoSphere Information Server 的服务器地址和端口号,默认端口号是 9080,输入用户名密码,点击下列列表框,选择安装的 InfoSphere Information Server 的引擎名称,全部选择完成后,点击登录。
图 1. administrator client 登录窗口
![图 1. administrator client 登录窗口](https://i-blog.csdnimg.cn/blog_migrate/72489f571b560d59ef397d0b82c00d21.png)
登录成功,会进入如下图 2 所示项目选择窗口,点击 Projects 所在 tab,选择正确的项目,点击属性,进入属性选择窗口。
图 2. 项目选择窗口
![图 2. 项目选择窗口](https://i-blog.csdnimg.cn/blog_migrate/f83372415d77184d317c07fe92b77d2f.png)
选择项目的属性窗口,如下图 3 所示,选择 Enable Runtime Column Propagation for Parallel Jobs。
图 3. 项目属性设置窗口
![图 3. 项目属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/3a930f7db0a31428b2781132485fe60e.png)
通常使用 RCP 技术,我们还要在作业的设计中,启用多实例,如下图 4 所示。这样可以复用同一个作业,在同一时间处理不同的数据流。
图 4. 作业属性设置窗口
![图 4. 作业属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/5344e8a687dcfea134a1368ba0980a8d.png)
创建 schema 文件
Schema 文件包含数据记录的格式的定义,包含每一列的名称和类型,如下清单 1 就是一个简单的 schema 文件的例子。
清单 1. schema 文件
1
2
3
4
5
6
7
|
record
{final_delim=final_delim tring, delim= delim string, quote=quote sting}
(
Column name 1:data type1;
Column name 2:data type 2
//a comment input here
)
|
每一列的定义用分号分隔,每一列的定义如下格式。
Column_name: [nullability] datatype
列名称必须以字符或者下划线开头,包含字符数字下划线的字符串,不区分大小写。
Nullability 是表示某列是否允许为空,如果允许为空,那么是 nullable,如果不为空,则 not nullable。这一属性也可以应用于记录级,如果应用于记录,列级别的属性就会被覆盖。
例如,如下清单 2 所示定义,包括 column_1 在内的所有列可空。
清单 2. nullable 举例
1
2
3
4
5
|
record nullable (
column_1:not nullable string[30];
column_2:int32;
column_3: date
)
|
Datatype 采用的是内部的数据类型,不是阶段定义的 SQL 的数据类型。
下面介绍各种数据类型的列定义的表示。
Date 类型如下清单 3 所示。
清单 3. date 定义举例
1
2
3
4
|
record (column_1:date; ) // 简单的日期
record (column_2[10]:date; ) // 长度为 10 的日期数组
record (column_3[]:date; ) // 变长日期数组
record (column_4:nullable date;) // 可空日期类型
|
Decimal 类型:类型定义如下。
column_name:decimal[ precision, scale]
需要给出 decimal 类型的有效位数和小数位数,precision 表示有效位数只包括整数和小数部分的所有有效长度,scale 表示小数位数的长度。不给定 scale 默认为 0。
如下面清单 4 所示例子。
清单 4. decimal 定义举例
1
2
3
|
record (column_1:decimal[12]; ) // 表示 12 位整数
record (column_2[10]:decimal[15,3]; )// 长度为 10 的 decimal 数组
record (column_3:nullable decimal[15,3];) // 可空 decimal
|
浮点型数据:浮点型数据分为单精度数据 sfloat 和双精度 dfloat,如下清单 5 所示例子。
清单 5. float 定义举例
1
|
record (single_column:sfloat; double_column:dfloat; )
|
整数类型:整数类型可以定义 8,16,32 或者 64 位整数型,分为带符号已经不带符号,如下清单 6 所示举例。
清单 6. integer 定义举例
1
2
|
record (column_1:int32;) // 32 位带符号整数
record (column_2:nullable int64;) // 可空 64 位带符号整数
|
字符串类型:字符串类型可以定义固定长度和变长字符串,如下清单 7 所示举例。
清单 7. string 定义举例
1
2
3
|
record (var1:string[];) // 变长字符串
record (var3:string[80];) // 固定长度为 80 个字节的字符串
record (var4:nullable string[80];) // 可空固定长度字符串
|
Schema 文件的创建要复杂一些,格式稍有问题,就会导致作业失败,但是笔者发现了一个比较巧妙的办法。我们以时间维度为例,首先 import 描述文件的 table definition,在 DataStage designer client 中双击打开我们导入的 table definition,选择 layout,选择 parallel 选项,将显示该表定义的 schema 文件格式,我们只要稍加修改,就能得到我们要的 schema 文件,如下图 5 所示。
图 5. 表定义的 schema 格式
![图 5. 表定义的 schema 格式](https://i-blog.csdnimg.cn/blog_migrate/c263f2ad01ba0495950c546b0a2874a4.png)
将 quota=double 替换为 quota=none,在列定义去掉扩张的属性,以及描述列如何生成的信息,也就是把大括号以及括号内的属性去掉,最终的 schema 文件如下清单 8 所示。
清单 8. schema 举例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
record
{final_delim=end, delim=',', quote=none}
(
dt_dimnsn_id:int32;
fiscal_yr: int32;
quarter_id: int32;
fiscal_qtr: int32;
quarter_display: string[2];
month_id: int32;
fiscal_mth: int32;
days_in_month: int32;
month_name: string[15];
date_display: string[15];
day_of_week: int16;
day_of_month: int16;
day_of_year: int16;
week_of_month: int16;
week_of_quarter: int16;
week_of_year: int16;
weekday: string[15];
fiscal_date: date;
inact_flag: int16;
add_date: timestamp;
add_by_user: string[max=210];
mod_date: timestamp;
mod_by_user: string[max=210];
)
|
RCP 的应用
假设某大型企业销售部门有如下需求,要同时导入不同数据源的数据,来指导销售部门的经营策略的指定。这些数据可能是销售人员的绩效数据,也可能是销售人员的地理信息,或者销售人员的人事信息,销售人员的变动信息等,这些数据组织在数据仓库汇总。基于安全性考虑,所有的数据都会以文件形式,ftp 到某个服务器,需要将文件中的数据导入到 DB2 数据库中。
明确需求以后,现在需要设计 datastage 作业,导入到数据库中,如果不采用 RCP 技术,那么我们将需要为每一种数据源,单独设计一套作业,这种重复性付出是单调和乏味的,显然这种做法不能有效的复用作业。
本文设计如下,采用两层结构。底层导入数据的核心作业设计为 parallel 作业,负责将运行时指定的特定路径下的文件,按照指定的 schema 格式,导入到指定的数据库的表中。其次,上层设计 sequence 作业,循环等待文件的出现,发现文件出现,则调用底层作业,将文件导入到数据库。
首先看底层作业的设计,这个作业会用到两个 datastage 的阶段,分别是 Sequential File 阶段和 DB2 connector 阶段。
Sequential File 是一个文件型阶段,他可以让你从一个平文件中读取或者写入数据。DB2 connector 是一个支持并行读写的 DB2 阶段,多个并行的流程的分布取决于 DB2 的分区优化,而且 DB2 connector 是唯一一个 datastage 支持优化的 DB2 阶段。
打开 datastage designer 客户端,创建新作业,命名为 test_file_to_db,定义作业参数,提供给上层作业调用时赋值。
如图 6 所示,为作业创建了参数及含义如下。
- Source_File: 数据源文件的路经
- Schema_File: schema 文件路经
- Target_DB_Name: 目标数据库名称
- Target_DB_User: 目标数据库上的用户名
- Target_Password: 目标数据库上的用户的密码
- Target_Table_Name: 要插入的目标数据库表名称
图 6. test_file_to_db 参数
![图 6. test_file_to_db 参数](https://i-blog.csdnimg.cn/blog_migrate/d74a81ea828817d8d24dece9df570ef4.png)
把 sequential 阶段和 DB2 connector 阶段拖入,创建作业如下图 7 所示设计窗口。
图 7. test_file_to_db 设计窗口
![图 7. test_file_to_db 设计窗口](https://i-blog.csdnimg.cn/blog_migrate/ea754d2882d253a4679e6ecb5ceebe7f.png)
双击 Source_File,打开 output 的 Properties,如下图 8 所示,设置 File 属性为 #Source_File#,Schema File 属性的值为 #Schema_File#,如果源文件首行包括字段名称,还要设置 First Line is Column Names 为 True。
图 8. Source_File 阶段属性设置窗口
![图 8. Source_File 阶段属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/1a2e31b92ec6b30cde94abd79cb743a2.png)
再设置好相应的 DB2 Connector 的属性,如下图 9 所示,编译作业成功。
图 9. Target_DB 属性设置窗口
![图 9. Target_DB 属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/794b46892c065482cbeb0f5822fb9f37.png)
上层作业设计如下。
如图 10 所示,设计如下 sequence 任务,这个任务分为五部分,保存为 test_RCP。
- 初始化参数
- 发送邮件通知作业开始运行
- 循环等待文件出现
- 调用作业导入
- 发送邮件通知作业成功结束
图 10. test_RCP 设计窗口
![图 10. test_RCP 设计窗口](https://i-blog.csdnimg.cn/blog_migrate/72c2a44dedc5e7ea01451b233347a7f8.png)
首先点击任务属性,打开如下图 11 所示属性窗口,我们看一下系统参数设置,我们定义了三个自定义参数,其余都是项目参数。
图 11. test_RCP 属性窗口
![图 11. test_RCP 属性窗口](https://i-blog.csdnimg.cn/blog_migrate/544e9c2353a95952f129a6cad59f2439.png)
双击 Initialize_Param 这个阶段,我们看下如下图 12 所示参数初始化。我们看到,这里的主要工作是,参数转行和转换,将作业定义的参数,转化为作业可以直接使用的参数,例如将文件路径和文件名转换为文件的绝对路径。
参数的含义如下所示。
- V_DB_NAME:目标数据库名称
- V_DB_USER:目标数据库用户名
- V_DB_PASS:目标数据库用户名密码
- V_Source_File:数据源文件绝对路径
- V_Schema_File:schema 文件绝对路径
- V_Target_Table_Name:目标数据表名
图 12. 参数初始化窗口
![图 12. 参数初始化窗口](https://i-blog.csdnimg.cn/blog_migrate/ea14fa7f20db6b7ceba051b6ba12e0d8.png)
双击 Wait_For_File 阶段,参数设置如下图 13 所示,在这里引用了,前面我们初始化的文件参数,并且设置文件等待的时间,如果希望永远等待,那么勾选 Do not timeout。
图 13. Wait_For_File 阶段窗口
![图 13. Wait_For_File 阶段窗口](https://i-blog.csdnimg.cn/blog_migrate/4ff8d5ce617bd29e3fcc49bd00ead723.png)
在作业 name 中选择本文创建好的下层作业 test_file_to_db, 参数窗口中的参数设置如下图 14 所示。
图 14. xls_to_DB 阶段属性设置窗口
![图 14. xls_to_DB 阶段属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/0d0caffdaf3147127bd833338e1d8fb8.png)
双击 Notify_Job_Start 阶段,打开如下图 15 所示的邮件发送参数配置,配置在参数初始化阶段初始化的参数,包括邮件发送的 host,发送方邮件地址,以及接收端邮件地址。本文设置的邮件的主题包括了作业的名称,作业的状态等信息。
图 15. xls_to_DB 阶段属性设置窗口
![图 15. xls_to_DB 阶段属性设置窗口](https://i-blog.csdnimg.cn/blog_migrate/885a0e193065903a0d798e7b8e2a8356.png)
这样,本文的作业以及创建,编译完成,下面我们来测试这个作业。
首先,本文导入如下图 16 所示数据源,导入目标数据表名为 emp_job_role。
图 16. 数据源文件 1
![图 16. 数据源文件 1](https://i-blog.csdnimg.cn/blog_migrate/149a5368ebd8a72d653999bcbbe985ae.png)
Schema 文件内容如下清单 9 所示。
清单 9. 数据源 1 的 schema
1
2
3
4
5
6
7
8
9
|
record
{final_delim=end,delim=',',quote=none}
(
Emp_Id:int32;
Emp_Name:string[max=30];
Emp_Dept_Id:int32;
Emp_Dept_Name: string[max=40];
Job_Role_Desc: string[max=30];
)
|
运行作业导入数据后,数据库中数据入下图 17 所示。
图 17. test_RCP 运行结果 1
![图 17. test_RCP 运行结果 1](https://i-blog.csdnimg.cn/blog_migrate/c20e62a80ad3c171c56d22fa329ef182.png)
改变数据源,如下图 18 所示,导入到目标数据表 emp_geogphy。
图 18. 数据源文件 2
![图 18. 数据源文件 2](https://i-blog.csdnimg.cn/blog_migrate/c1d16090f95697a6cc224c06361b4047.png)
修改 schema 文件如清单 10 所示。
清单 10. 数据源 2 的 schema
1
2
3
4
5
6
7
8
9
10
11
|
record
{final_delim=end,delim=',',quote=none}
(
EMP_ID:int32;
EMP_NAME:string[max=30];
EMP_DEPT_ID:int32;
EMP_DEPT_Name: string[max=40];
Job_Role_Desc: string[max=30];
Prod_Line_Desc: string[max=30];
Geogphy_Desc: string[max=30];
)
|
重新运行作业,得到如下图 19 所示结果。
图 19. Populate_Emp 运行结果 2
![图 19. Populate_Emp 运行结果 2](https://i-blog.csdnimg.cn/blog_migrate/d7d4587fc4f248f0de81b3a4301e0ff5.png)
这样本文就实现了设计要求,应用 RCP 技术,实现了动态改变数据作业的表定义,从而达到在不同数据源中导入数据。
结束语
本文详细介绍了 RCP 在 Infosphere datastage 下的一个典型应用,通过假设典型的应用场景,本文一步步带领读者定义 schema 文件,创建了 datastage 作业,最后使用作业导入了两个不同的数据源到数据库,导入结果表明,RCP 在 datastage 作业中的使用方便,高效。希望能帮助您初步了解了 RCP,创建高效的 datastage 作业可以起到帮助,谢谢阅读。