开篇介绍
通常一个 ETL Package 是由多个控制流和数据流共同组成,有的时候 ETL 的步骤可能会比较多,整个流程执行下来的时间可能比较长。假设在 ETL Package 中包含5个Task,前3个Task执行超过1个小时,到了第4个Task的时候发生失败。如果下次执行的时候重新从第1个任务开始执行,那么又要花费1个小时等待 1-3 任务执行,无疑在效率上讲是非常低的。特别是在数据仓库的应用上,往往从数据源到Staging的过程中有千万级甚至亿级的数据要加载,加载完毕之后再进入到维度和事实表。如果在进入维度和事实表的过程中发生失败,就意味着下次需要重新加载数据到Staging表。而通过检查点CheckPoint的设置可以解决这个问题,通过合理的设置可以跳过上一次已经成功执行过一些步骤而直接从失败的地方重新开始执行,这样大大的提高了包的执行效率。
案例演示
下面这个 ETL 示例简单的模拟了从一个数据源抽取数据然后输出到一个数据表和一个平面文件的过程,之后再看 CheckPoint 的使用。
USE BIWORK_SSIS
GO
IF OBJECT_ID('CK_Address') IS NOT NULL
DROP TABLE CK_Address
GO
IF OBJECT_ID('CK_AddressAudit') IS NOT NULL
DROP TABLE CK_AddressAudit
GO
CREATE TABLE CK_Address
(
AddressID INT,
AddressLine1 NVARCHAR(60),
AddressLine2 NVARCHAR(60),
City NVARCHAR(30)
)
CREATE TABLE CK_AddressAudit
(
ID INT PRIMARY KEY IDENTITY(1,1),
CityName NVARCHAR(60),
Counts INT
)
ETL 过程
- EST_TruncateAddress - TRUNCATE TABLE dbo.CK_Address TRUNCATE TABLE dbo.CK_AddressAudit
- DFT_LoadAddress - 从 AdventureWorks2012.People.Address 中抽取数据到 dbo.CK_Address 中
- DFT_SaveAddressAudit - 对 CK_Address 表中的数据做出一些统计然后写入到 dbo.CK_AddressAudit 中
- DFT_OutputAddressAudit - 将 dbo.CK_AddressAudit 中的数据输出到一个文本文件中
输出结果- CK_Address 和 CK_AddressAudit
输出的文件
假设在最后一个步骤发生错误,那么在下次执行 Package 的时候,前面所有的步骤都需要被重新执行。
CheckPoint 的设置过程
通过设置 CheckPoints 可以解决这个问题,要使用检查点首先要在包中开启检查点这一功能,并且可以在相应的容器和控制流 Task 中写检查点。
第一步,找到 SSIS Package 的属性,设置 SaveCheckPoints 属性为 Ture,这样就允许 SSIS Package 在执行过程中保存检查点。
第二步,在 CheckPointFileName 属性中,提供一个文件名和路径,这样 SSIS Package 就会用这个文件来维护执行过程中的状态信息。假设一个包执行失败了然后重新启动它,那么包就可以读这个检查点文件来找到最后一次执行成功的 Task 然后决定从哪里开始重新执行,一个包只能有一个检查文件。
第三步,设置 CheckpointUsage 属性为 IfExists。这样如果检查点文件不存在的时候包会从头开始执行,如果存在就会根据相应的状态信息从指定的 Task 开始执行。
第四步,当在包中启用了检查点信息的话,最后的一个步骤就是在包中各种 Task 上来设置检查点,这时需要将相应的容器或者Task的 FailPackageOnFailure 属性设置为 True,此处修改的是 DFT_OutputAddressAudit 属性。
设置保存完 SSIS Package 之后再次运行,仍然在 DFT_OutputAddressAudit 处会发生错误,并且 SSIS Package 会输出一个检查点文件。
可以看看这个检查点文件。
<DTS:Checkpoint xmlns:DTS="www.microsoft.com/SqlServer/Dts" DTS:PackageID="{66363AAC-346A-4225-BE24-34538C1DF296}">
<DTS:Variables DTS:ContID="{66363AAC-346A-4225-BE24-34538C1DF296}"/>
<DTS:Container DTS:ContID="{FCABC727-26BD-4C73-AA26-2B31BCC2C3E1}" DTS:Result="0" DTS:PrecedenceMap="Y"/>
<DTS:Container DTS:ContID="{11182445-3759-4699-88E8-345105620B53}" DTS:Result="0" DTS:PrecedenceMap=""/>
<DTS:Container DTS:ContID="{DA2ED97D-2D6E-4401-A36E-1A9A28B51C37}" DTS:Result="0" DTS:PrecedenceMap=""/>
<DTS:Container DTS:ContID="{5DC475B3-C3DC-4118-8116-4DC1FF8CA5E2}" DTS:Result="0" DTS:PrecedenceMap="Y"/>
</DTS:Checkpoint>
修改好 DFT_OutputAddressAudit 然后再次运行,发现这次直接是从 DFT_OutputAddressAudit 处开始执行,这样就不需要重复执行已经成功过的步骤。
执行成功之后,这个检查点文件将会被 SSIS Package 删除掉。
CheckPoint 执行过程解析
启用了检查点的 Package 在重新执行的时候它的执行过程通常是这样的:
第一步,检查 Checkpoints 文件是否存在。如果不存在的话,那么包将从头开始执行。如果存在,包将读取这个文件并找到应该从哪一个 Task 开始执行。并且也会从中读取一些有关如何从上一次失败的时候要如何更新相应的变量和连接信息。
第二步,更新每一个设置过 Checkpoint (FailPackageOnFailure = True) 的那些已经执行成功的Task的状态,记录下来更新到 Checkpoint 文件。
第三步,如果包执行失败,那么 Checkpoint 文件将不会改变并只会保留上一次执行成功的 Task 的信息。
第四步,如果包执行成功,那么 Checkpoint 文件就会被删除掉。那么下一次包再运行的时候,Checkpoint 文件将不会存在,这样包又会继续从第一个 Task 开始执行。
如果将 CheckpointUsage 属性设置为 Always, 那么检查文件必须存在否则包将不会执行。另外,如果包设置了 TransactionOption = Required 的话,将不允许使用 Checkpoints 这一机制。
在一个包有着非常多而复杂的子流程情况下,无疑通过启用检查点将会节省大量的时间,因为它可以跳过那些在上一次已经成功的 Task 而直接从失败的 Task 那里重新执行。当然在 Data Flow Task 上可以设置检查点,但是对于在 Data Flow Task 内部将不能设置,因为 Checkpoint 只支持到 Control Flow Task 这一层,而不会支持 Data Flow 这一层。