load_dim_customer转换
load_dim_customer是作业load_rentals中第二个执行的转换。
目的是加载dim_customer维度表。
load_dim_customer转换的结构同笔记(四)的load_dim_staff转换比较:
1. 转换开始的地方是两个 “ 表输入 ” 步骤,用来捕获并抽取变更的数据。
2. 转换结束的地方使用 “ 维度查询/更新 ” 步骤来维护类型2的缓慢变化客户维度,并把数据加载到维度表dim_customer。
3. 数据加载到维度表dim_customer之前,表customer中的active列的值被转换为Yes或者No。
- Fetch Customer Address子转换
相比load_dim_staff转换,load_dim_customer转换包含了一个特殊的步骤:Fetch Customer Address,这是一个映射步骤(子转换),允许重复调用一个存在的转换。
在其配置信息中,可以看到Fetch Customer Address使用了fetch.address.ktr转换。
fetch_address子转换:
1. 地址数据级联查询
转换fetch_address中包括了一系列的 “ 数据库查询 ” 步骤,这些步骤包括Lookup Address、Lookup City和Lookup Country。这些步骤形成了级联查询:
Lookup Address 步骤使用输入流的address_id字段在address表中查询到对应的数据行,然后作为查询结果字段之一的city_id增加到输出流;
接下来,Lookup City步骤使用这个字段在表city中获得对应数据行,并把country_id增加到输出流;
最后,country_id作为查询条件从country中获得对应的数据行,至此,输出流中已经获得了输入流中address_id对应的所以地址数据行。
2. 更多的反正规划:拼接地址信息
在sakila数据库中,address表用两列address和address2来存放多行地址,但是dim_customer维度表和dim_store维度表只有一个地址字段,所以必须要处理多行地址。
fetch_address转换里有一个过滤步骤,名为 “ Is there a second address line?” 。这个步骤将地址输入流分为两个输出流:一个数据流是多行地址的情况,另一个数据流是单行地址的情况。
在fetch.address子转换中,多行地址是 “ 过滤 ” 步骤的 “ true ” 输出,对应的连接线上有一个对钩号的标记。后面再使用Java脚本步骤处理这些地址:把多行地址合成一个字段。
无论是多行还是单行地址,数据最终都流向 “ 字段选择 ” 步骤,在这个转换中,“ 字段选择 ” 步骤只选择输出需要的字段,丢弃了所有类似city_id和country_id这样的字段。
虽然也可以输出 fetch_address转换里产生的所有字段,但不建议这样做,因为这样所有调用这个子转换的转换不得不计算哪些字段是有用的哪些是没用的。另外,一个外部转换可能有意无意地使用了子转换输出的某些字段。所以在维护fetch_address子转换时,需要确认这些字段是否被使用。
3.子转换接口
fetch_address转换开始和结束步骤分别是 “ 映射输入规范 ” (步骤名称 “ Input address_id ” )和 “ 映射输出规范 ” (步骤名称 “ Output Address ” )步骤。任何子转换都需要这两个步骤,它们是子转换的接口。
“ 映射输入规范 ” 步骤可以看作是特殊的输入步骤,该步骤把外部转换的数据注入到子转换里,同时也定义了要使用输入数据流中的哪几个字段。例如, “ Input address_id ” 步骤指定了需要从输入流中获取一个input_id字段。“ 映射输出规范 ” 步骤可以看作是特殊的输出步骤,它定义了本地转换的数据流从哪里传给外部转换。
- 配置Fetch Customer Address步骤
该步骤使用了fetch_address.ktr转换。 “ 映射(子转换)” 允许使用变量来替换特定的转换文件,规则与转换作业项相同。
注意:
这个例子中使用的变量和转换作业项里使用的变量略不同,作业中使用是 ${Internal.Job.Filename.Directory} 这个内置变量的路径是一个特定的相对路径。
而Fetch Customer Address步骤中变量将Job替换成了Transformation,在运行环境下,这个变量指的是load_dim_customer这个转换所在的路径。
Fetch Customer Address步骤也可以使用Internal.Job.Filename.Directory变量,但是这样得到的位置是load_rentals作业的文件位置,因为load_dim_customer转换是通过作业调用的。
在例子中,由于作业的文件位置和转换的文件位置处于同一个目录,因此从load_rentals作业中调用load_dim_customer转换时,这两个变量的取值并没有什么区别,但是这里必须明确Internal.Job.Filename.Directory和Internal.Transformation.Filename.Directory并不一定是同一个路径。假如直接运行转换load_dim_customer(不通过作业调用),变量Internal.Job.Filename.Directory由于没有初始化而不可用,然而Internal.Transformation.Filename.Directory变量仍然指向当前转换文件的路径。 - 从功能上来说
Fetch Customer Address步骤的目的是为了查找客户的地址,这种做法对于反正规划的维度表dim_customer是非常有必要的,维度表里的数据来自sakila.address表以及和它相关的sakila.city、sakila.country表。dim_store维度表同样也是反正规化设计的,也需要引用地址数据,所以我们要把获取地址的转换作为子转换,供不同转换使用。 - 注意:
“ 映射(子转换)” 步骤同一些程序语言中把某个代码源文件导入到主程序中有些类似,由于创建和测试一块逻辑代码需要耗费许多时间,因此任何需求变更或者bug修复都应该在一个模块当中,以提高系统的复用性。