使用 SSIS 中的 SQL 执行任务加载维度(SCD 类型 1 和类型 2)






4.95/5 (5投票s)
使用SQL任务加载维度比使用SCD转换性能更好。
引言
在BI环境中使用执行SQL任务加载维度表比在SSIS转换中使用SCD转换性能更好。
- SCD代表缓慢变化维度
- 此代码已在SQL Server 2008上测试过
为什么需要它?
在BI环境中,有几种方法可以加载维度表,例如,使用缓慢变化维度转换或使用合并联接转换等,但是这两种方法都非常适合少量数据,因为这些转换是异步的,它们对数据源的每一行数据执行操作,因此假设我们在数据源中有数百万条记录,那么加载维度表将花费很长时间,我认为您的业务不允许这样做。 因此,我们可以在SSIS中使用一个简单的执行SQL任务来减少处理时间,即使我们在数据源中有数百万条记录。
缓慢变化维度有三种类型:SCD类型1(更改属性),这意味着对于定义为SCD类型1的列不维护任何历史记录;例如,员工的电话号码。 第二种是SCD类型2(历史属性),这意味着通过使用开始日期/结束日期或通过使用版本号来维护历史记录; 例如,当任何员工的工作地点发生更改时,我们将通过使用开始日期/结束日期来维护旧员工位置的历史记录。 第三种SCD类型是我们在本文中考虑的内容。
在使用此方法(即SSIS中的执行SQL任务转换)加载维度表时,我们还可以维护SCD类型1和SCD类型2。
了解将在执行SQL任务下运行的脚本
对于SCD类型2:
对于SCD类型2,我考虑了以下列
城镇
客户名称,出生日期,电话号码,驾驶执照号码,职业
----For SCD type 2 Historical Attribute---
Declare @tempHistoricalAttribute As Table(CustomerId Int)
Insert Into @tempHistoricalAttribute(CustomerId)
select src.CustomerId from
(
select CustomerId,town from Customer
EXCEPT
select CustomerId,town from CustomerUpdate Where EndDate Is NULL
) src
Inner Join CustomerUpdate dst On src.CustomerId = dst.CustomerId
Where dst.EndDate Is NULL
Update CustomerUpdate Set EndDate = GETDATE() from
@tempHistoricalAttribute src
Inner Join CustomerUpdate dst On src.CustomerId = dst.CustomerId
Where dst.EndDate Is NULL
Insert Into CustomerUpdate(CustomerId,CustomerName,DateOfBirth,Town,TelephoneNo,
DrivingLicenceNo,Occupation,StartDate,EndDate)
Select CustomerId,CustomerName,DateOfBirth,Town,TelephoneNo,
DrivingLicenceNo,Occupation,GETDATE(),null From Customer where CustomerId in
(Select customerid from @tempHistoricalAttribute)
对于SCD类型1:
对于SCD类型1,我考虑了以下列
客户名称,出生日期,电话号码,驾驶执照号码,职业
-- To Maintain SCD type 1 Changing Attribute----
Update CustomerUpdate SET
CustomerName=src.CustomerName,DateOfBirth=src.DateOfBirth,
TelephoneNo = src.TelephoneNo,DrivingLicenceNo = src.DrivingLicenceNo,
Occupation = src.Occupation
from
(
select CustomerId,CustomerName,DateOfBirth,TelephoneNo,DrivingLicenceNo,
Occupation from Customer
EXCEPT
select CustomerId,CustomerName,DateOfBirth,TelephoneNo,DrivingLicenceNo,
Occupation from CustomerUpdate where EndDate Is Null
)src
INNER JOIN CustomerUpdate dest ON src.CustomerId = dest.CustomerId
where dest.EndDate Is Null
对于新记录:
--To Insert new Record------
Insert Into CustomerUpdate(CustomerId,CustomerName,DateOfBirth,Town,TelephoneNo,
DrivingLicenceNo,Occupation,StartDate,EndDate)
select src.CustomerId,src.CustomerName,src.DateOfBirth,src.Town,
src.TelephoneNo,src.DrivingLicenceNo,src.Occupation,GETDATE(),NULL
from
(
select CustomerId,CustomerName,DateOfBirth,Town,TelephoneNo,DrivingLicenceNo,
Occupation from Customer
EXCEPT
select CustomerId,CustomerName,DateOfBirth,Town,TelephoneNo,DrivingLicenceNo,
Occupation from CustomerUpdate where EndDate Is Null
)src
需要注意的重要事项
脚本应按以下顺序运行。 执行SQL任务将按以下顺序运行脚本
- 顺序 1:SCD类型2脚本
- 顺序 2:SCD类型1脚本
- 顺序 3:新记录脚本
创建项目
表脚本
if exists (select * from sys.tables where name = 'Customer')
drop table Customer
go
create table Customer
(
CustomerId int not null primary key,
CustomerName varchar(30), DateOfBirth date, Town varchar(50),
TelephoneNo varchar(30), DrivingLicenceNo varchar(30), Occupation varchar(30)
)
go
-- Populate Customer Source
declare @i int, @si varchar(10), @startdate date
set @i = 1
while @i <= 10
begin
set @si = right('0'+CONVERT(varchar(10), @i),2)
insert into Customer
( CustomerId, CustomerName, DateOfBirth, Town, TelephoneNo, DrivingLicenceNo, Occupation)
values
( @i, 'Customer'+@si, DATEADD(d,@i-1,'2000-01-01'), 'Town'+@si,
'Phone'+@si, 'Licence'+@si, 'Occupation'+@si)
set @i = @i + 1
end
go
-- Create customer table
if exists (select * from sys.tables where name = 'CustomerUpdate')
drop table CustomerUpdate
go
create table CustomerUpdate
(
Dim_CustomerId int identity(1,1),
CustomerId int not null,
CustomerName varchar(30), DateOfBirth date, Town varchar(50),
TelephoneNo varchar(30), DrivingLicenceNo varchar(30), Occupation varchar(30),
StartDate DateTime,EndDate Datetime
)
go
-- Populate Customer Destination
declare @i int, @si varchar(10), @startdate date
set @i = 1
while @i <= 5
begin
set @si = right('0'+CONVERT(varchar(10), @i),2)
insert into CustomerUpdate
( CustomerId, CustomerName, DateOfBirth, Town, TelephoneNo,
DrivingLicenceNo, Occupation,StartDate,EndDate)
values
( @i, 'Customer'+@si, DATEADD(d,@i-1,'2000-01-01'), 'Town'+@si,
'Phone'+@si, 'Licence'+@si, 'Occupation'+@si,GETDATE(),NULL)
set @i = @i + 1
end
go
步骤1. 创建SSIS包
打开SQL Server商业智能开发工作室并创建新项目作为SQL Server Integration Services,添加新包后。
步骤 2. 从工具箱中添加执行SQL任务,重命名为加载维度,然后编辑SQL任务。 然后在连接属性中设置连接凭据和数据库。
步骤 3:单击SQL语句属性中的按钮,然后编写SQL脚本
测试包
测试步骤 1:
运行包并查看结果
已插入5条新记录,客户ID为6到10。
测试步骤 2:
使用脚本更新记录
--for SCD type 1--
UPDATE [Customer]
SET [CustomerName] = 'aaa1'
,[DateOfBirth] = '2012-01-01'
WHERE [CustomerId] =1
GO
--for SCD type 2--
UPDATE [Customer]
SET [Town] = 'ttt1'
WHERE [CustomerId] =2
现在再次运行包,您将看到结果
客户ID = 1的CustomerName和dateOfBirth记录将被更新,但不会插入任何新记录因为SCD类型1。
此外,客户ID = 2的结束日期将被更新,并且将为客户ID = 2插入一条新记录,但将生成新的代理键,即Dim_CustomerId = 11
,结束日期为null因为SCD类型2。
关注点
这种方法比用于BI环境中维度加载的 SCD转换 和合并联接表现更好。