初始数据加载(二)
在数据仓库使用前,仓库当中无历史数据,需要通过初始数据加载将源数据库中数据加载到数据仓库。加载多长时间历史数据以及什么时候开始加载等由最终用户决定,比方说数据仓库将从2016-3-1号开始使用定期加载,最终用户要求加载两年历史数据。那么2016-3-1将加载2016-2-19号以及以前的所有历史数据加载至数据仓库,2016-3-2号开始定期加载2016-3-1 数据,每天定期加载前一天的数据。在加载历史数据事实数据之前,需要将历史的维度表数据均加载到数据仓库,原因是事实表的键引用到了维度表的技术键。在之前有讲到一个项目,由于维度表分为跟事实数据相关联的,和直接从源数据系统计算得出的维度表两种,这两种维度表在相应的加载过程当不尽相同。虽然这两种方式的加载方式约有不通,但原则上还是先加载所有维度表再加载事实表。
在加载数据之前,我们必须确认数据源以及数据仓库的表可用,以及源和仓库相应表特性,如表字段特性以及通过什么变换成仓库对应表字段。在ETL之前我们需要做一个源和目标的MAPPING关系。表二-1为本实例中需要的数据源以及目标仓库表等属性。生成这个表格的过程叫做数据源映射。
|
源数据 |
源数据类型 |
文件名/表名 |
数据仓库中的目标表 |
|
客户 |
MySQL表 |
customer |
customer_dim |
|
产品 |
MySQL表 |
product |
product_dim |
|
销售订单事务 |
MySQL表 |
sales_order |
order_dim |
|
sales_order_fact |
|||
|
date_dim(如果使用“从源数据装载日期”方法,本示例中使用的预装载) |
表(三)- 1
上表已经标识出源和目标表间的Mapping关系,更加详细的字段MAPPING关系表将在后续给出。
| 文件名/表名 | 数据仓库中的目标表 | ||||
| Customer | customer_dim | ||||
| Column_name | type | length | Column_name | type | length |
| Customer_number | int | 4 | Customer_city | varchar | 30 |
| Customer_zip_code | int | 4 | Customer_name | varchar | 50 |
| Customer_name | varchar | 50 | Customer_number | int | 4 |
| Customer_street_address | varchar | 50 | Customer_sk | int | 4 |
| Customer_city | varchar | 30 | Customer_state | varchar | 2 |
| Customer_state | varchar | 2 | Customer_street_address | varchar | 50 |
| Customer_zip_code | int | 4 | |||
| effective_date | datetime | 8 | |||
| expiry_date | datetime | 8 | |||
| 文件名/表名 | 数据仓库中的目标表 | ||||
| Product | Product_dim | ||||
| Column_name | type | length | Column_name | type | length |
| Product_name | varchar | 30 | Product_sk | int | 4 |
| Product_code | int | 4 | Product_name | varchar | 30 |
| Product_category | varchar | 30 | Product_code | int | 4 |
| Product_category | varchar | 30 | |||
| expire_date | datetime | 8 | |||
| effective_date | datetime | 8 | |||
| 文件名/表名 | 数据仓库中的目标表 | ||||
| sales_order | order_dim | ||||
| Column_name | type | length | Column_name | type | length |
| Product_code | int | 4 | order_sk | int | 4 |
| Order_number | int | 4 | order_number | int | 4 |
| Order_mouunt | int | 4 | expire_date | datetime | 8 |
| Order_date | datetime | 8 | effective_date | datetime | 8 |
| Entry_date | datetime | 8 | |||
| Customer_number | int | 4 | |||
表字段Mapping关系确定以后,需要考虑维度变化情况。标识出了数据源,现在要考虑维度历史的处理。大多数维度值是随着时间改变的。客户改变了姓名,产品的名称或分类变化,销售订单的修正等等。当一个维度改变,比如一个产品有了新的分类,你必须维护维度的历史。在这种情况下,product_dim表里必须既存储产品老的分类,也存储产品当前的分类。并且,老的销售订单里的产品分类信息引用老的分类。渐变维(SCD)即是一种在多维数据仓库中实现维度历史的技术。有三种不同的SCD技术:SCD 类型1(SCD1),SCD类型2(SCD2),SCD类型3(SCD3).
- SCD1通过修改维度记录直接覆盖已存在的值,它不维护记录的历史。SCD1一般用于修改错误的数据。
- SCD2在源数据发生变化时,给维度记录建立一个新的“版本”,从而维护维度历史。SCD2不删除、修改已存在的数据。
- SCD3保持维本度记录的一个版。它通过给某个数据单元增加多个列来维护历史。例如,为了维护客户地址,customer_dim维度表有一个customer_address列和一个previous_customer_address列。SCD3可以有效的维护有限的历史,而不像SCD2那样维护全部历史。SCD3很少使用。它只适用于数据库空间不足并且用户接受有限维度历史的情况。
在本示例中,客户维度历史使用SCD1,产品维度历史的产品名称和产品类型属性使用SCD2。
Kettle里的“维度查询/更新”步骤可以用来方便处理SCD2类型的维度,但需要维度表里除了有生效日期和到期日期外,还要有一个“版本”字段,用来标识出维度历史的各个版本。虽然示例中只有产品维度使用SCD2,为了统一处理,使用清单(二)- 1里的脚本给所有维度表添加版本字段。
1 alter table dbo.Customer_dim add version int default 1 ; 2 alter table dbo.order_dim add version int default 1 ; 3 alter table dbo.Product_dim add version int default 1 ;
现在可以编写加载初始数据的脚本了。假设数据仓库加载2016-3-1号以前的数据,加载两年的历史数据,则需要导入2014-3-1至2016-2-29号的数据。
注意此实例处理产品以及客户维度表的生效日期为2014-3-1,装载的销售订单不会早于此日期,也就是说不需要早于2014-3-1号以前的维度数据,而订单维度的生效日期显然就是订单的生成日期。日期维度的数据已经生成,不再详细说明;
Sql实现历史数据装载,到此处已明确装载的时间范围以及源与目标的mapping关系。清单(二)-2为sql实现
1 use dw; 2 ---清空表数据 3 truncate table dbo.Customer_dim; 4 truncate table dbo.customer_stg; 5 truncate table dbo.order_dim; 6 truncate table dbo.Product_dim; 7 truncate table dbo.product_stg; 8 truncate table dbo.Sales_order_fact; 9 10 --源数据抽取到stage表 11 insert into dbo.customer_stg 12 select * from source.dbo.Customer; 13 insert into dbo.product_stg 14 select * from source.dbo.Product; 15 go 16 17 ---处理数据仓库维度表数据,抽取的时间为2014-3-1后的数据 18 19 insert into dbo.Customer_dim 20 ( 21 Customer_number 22 ,Customer_name 23 ,Customer_street_address 24 ,Customer_zip_code 25 ,Customer_city 26 ,Customer_state 27 ,effective_date 28 ,expiry_date) 29 select customer_number 30 ,customer_name 31 ,customer_street_address 32 ,customer_zip_code 33 ,customer_city 34 ,customer_state 35 ,\'2014-3-1\' 36 ,\'2099-12-31\' from dbo.customer_stg; 37 38 go 39 40 insert into dbo.Product_dim 41 ( 42 Product_code 43 ,Product_name 44 ,Product_category 45 ,effective_date 46 ,expire_date) 47 select 48 product_code 49 ,product_name 50 ,product_category 51 ,\'2014-3-1\' 52 ,\'2099-12-31\' from dbo.product_stg; 53 go 54 55 INSERT INTO [DW].[dbo].[order_dim] 56 ([order_number] 57 ,[effective_date] 58 ,[expire_date]) 59 select 60 Order_number 61 ,Order_date 62 ,\'2099-12-31\' from source.dbo.Sales_Order; 63 go 64 65 insert into dbo.Sales_order_fact 66 (Order_sk 67 ,Customer_sk 68 ,Product_sk 69 ,order_Date_sk 70 ,Order_amount 71 ) 72 select B.order_sk 73 ,D.Customer_sk 74 ,E.Product_sk 75 ,C.Date_sk,A.Order_mouunt from 76 source.dbo.Sales_Order A 77 ,dbo.order_dim B 78 ,dbo.date_dim C 79 ,dbo.Customer_dim D 80 ,dbo.Product_dim E 81 where A.Order_number=B.order_number 82 AND A.Customer_number=D.Customer_number 83 AND A.Order_date=C.date 84 AND A.Product_code=E.Product_code 85 AND A.Order_date >= \'2014-3-1\' 86 and A.Order_date <= \'2016-2-29\'; 87 88 GO
Kettle实现:
装载stage表的转换如下:
装载维度表: