(三)初始装载 在数据仓库可以使用前,需要装载历史数据。这些历史数据是导入进数据仓库的第一个数据集合。首次装载被称为初始装载,一般是一次性工作。由最终用户来决定有多少历史数据进入数据仓库。例如,数据仓库使用的开始时间是2015年3月1日,而用户希望装载两年的历史数据,那么应该初始装载2013年3月1日到2015年2月28日之间的源数据。在2015年3月2日装载2015年3月1日的数据,之后周期性地每天装载前一天的数据。在装载事实表前,必须先装载所有的维度表。因为事实表需要维度的代理键。这不仅针对初始装载,也针对定期装载。本篇说明执行初始装载的步骤,包括标识源数据、维度历史的处理、使用SQL和Kettle两种方法开发和测试初始装载过程。 设计开发初始装载步骤前需要识别数据仓库的每个事实表和每个维度表用到的并且是可用的源数据,并了解数据源的特性,例如文件类型、记录结构和可访问性等。表(三)- 1里显示的是本示例中销售订单数据仓库需要的源数据的关键信息,包括源数据表、对应的数据仓库目标表等属性。这类表格通常称作数据源对应图,因为它反应了每个从源数据到目标数据的对应关系。生成这个表格的过程叫做数据源映射。在本示例中,客户和产品的源数据直接与其数据仓库里的目标表,customer_dim和product_dim表相对应。另一方面,销售订单事务表是多个数据仓库表的源。
源数据 | 源数据类型 | 文件名/表名 | 数据仓库中的目标表 |
---|---|---|---|
客户 | MySQL表 | customer | customer_dim |
产品 | MySQL表 | product | product_dim |
销售订单事务 | MySQL表 | sales_order | order_dim |
sales_order_fact | |||
date_dim(如果使用“从源数据装载日期”方法,本示例中使用的预装载) |
表(三)- 1
标识出了数据源,现在要考虑维度历史的处理。大多数维度值是随着时间改变的。客户改变了姓名,产品的名称或分类变化,销售订单的修正等等。当一个维度改变,比如一个产品有了新的分类,你必须维护维度的历史。在这种情况下,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里的脚本给所有维度表添加版本字段。
代码语言:javascript复制USE dw;
-- 客户维度增加版本属性
alter table customer_dim add version int comment '版本序列号' not null default 1 after customer_state;
-- 产品维度增加版本属性
alter table product_dim add version int comment '版本序列号' not null default 1 after product_category;
-- 订单维度增加版本属性
alter table order_dim add version int comment '版本序列号' not null default 1 after order_number;
清单(三)- 1
现在可以编写用于初始装载的脚本了。假设数据仓库从2015年3月1日开始使用,用户希望装载两年的历史数据,则需要导入从2013年3月1日到2015年2月28日的源数据。清单(三)- 2里的SQL脚本用于完成初始装载过程。 注意:客户和产品维度的生效日期是2013年3月1日。装载的销售订单不会早于该日期,也就是说,不需要更早的客户和产品维度数据。订单维度的生效日期显然就是订单生成的日期。销售订单事实表的外键列由维度表的代理键导入。date_dim维度表的数据已经预生成,日期从2000年1月1日到2020年12月31日。
代码语言:javascript复制USE dw;
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE customer_dim;
TRUNCATE product_dim;
TRUNCATE order_dim;
TRUNCATE sales_order_fact;
TRUNCATE customer_stg;
TRUNCATE product_stg;
SET FOREIGN_KEY_CHECKS=1;
INSERT INTO customer_stg
SELECT
customer_number
, customer_name
, customer_street_address
, customer_zip_code
, customer_city
, customer_state
FROM source.customer ;
INSERT INTO customer_dim
SELECT NULL
, customer_number
, customer_name
, customer_street_address
, customer_zip_code
, customer_city
, customer_state
, 1
, '2013-03-01'
, '2200-01-01'
FROM
customer_stg ;
INSERT INTO product_stg
SELECT
product_code
, product_name
, product_category
FROM source.product ;
INSERT INTO product_dim
SELECT
NULL
, product_code
, product_name
, product_category
, 1
, '2013-03-01'
, '2200-01-01'
FROM product_stg ;
INSERT INTO order_dim
SELECT
NULL
, order_number
, 1
, order_date
, '2200-01-01'
FROM source.sales_order
WHERE order_date >= '2013-03-01'
AND order_date <= '2015-02-28' ;
INSERT INTO sales_order_fact
SELECT
order_sk
, customer_sk
, product_sk
, date_sk
, order_amount
FROM
source.sales_order a
, order_dim b
, customer_dim c
, product_dim d
, date_dim e
WHERE
a.order_number = b.order_number
AND a.customer_number = c.customer_number
AND a.product_code = d.product_code
AND a.order_date = e.date
AND order_date >= '2013-03-01'
AND order_date <= '2015-02-28';
COMMIT ;
清单(三)- 2
图(三)- 1到图(三)- 27显示使用Kettle转换进行初始装载的具体步骤。“初始装载”作业包含四个作业项,分别是一个“清空过渡区”SQL脚本、“装载过渡区”、“装载维度表”和“装载事实表”三个转换。
图(三)- 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
使用清单(三)- 3里的查询验证初始装载的正确性,事实表应该有19条数据,如图(三)- 28所示。
代码语言:javascript复制USE dw;
SELECT
order_number
, customer_name
, product_name
, date
, order_amount amount
FROM
sales_order_fact a
, customer_dim b
, product_dim c
, order_dim d
, date_dim e
WHERE
a.customer_sk = b.customer_sk
AND a.product_sk = c.product_sk
AND a.order_sk = d.order_sk
AND a.order_date_sk = e.date_sk
ORDER BY order_number;
清单(三)- 3
图(三)- 28