Friday, October 27, 2017

SSIS: Creating Dynamic Data-driven SSAS Partitions

SSIS: Creating Dynamic Data-driven SSAS Partitions

Partitions improve the query response of SSAS cube by narrowing the MDX query to a pre-defined subset of data. Usually cubes are developed with few basic partitions to begin with and new partitions are added over time. Partitions are created using XMLA commands. The rest of this post explains the steps to create partitions using metadata and SSIS package.

Metadata

First step is to identify the required data elements. This is done by scripting out the XMLA from an existing partition. The XMLA will be similar to the one shown below
    <ParentObject>
        <DatabaseID>AdventureWorksDW</DatabaseID>
        <CubeID>Adventure Works</CubeID>
        <MeasureGroupID>Fact Internet Sales 1</MeasureGroupID>
    </ParentObject>
    <ObjectDefinition>
        <Partition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ID>Internet_Sales_2007</ID>
            <Name>Internet_Sales_2007</Name>
            <Source xsi:type="QueryBinding">
                <DataSourceID>Adventure Works DW</DataSourceID>
                <QueryDefinition>SELECT [dbo].[FactInternetSales].[ProductKey],[dbo].[FactInternetSales].[OrderDateKey],[dbo].[FactInternetSales].[DueDateKey],[dbo].[FactInternetSales].[ShipDateKey], [dbo].[FactInternetSales].[CustomerKey], [dbo].[FactInternetSales].[PromotionKey],[dbo].[FactInternetSales].[CurrencyKey],[dbo].[FactInternetSales].[SalesTerritoryKey],[dbo].[FactInternetSales].[SalesOrderNumber],[dbo].[FactInternetSales].[SalesOrderLineNumber],[dbo].[FactInternetSales].[RevisionNumber],[dbo].[FactInternetSales].[OrderQuantity],[dbo].[FactInternetSales].[UnitPrice],[dbo].[FactInternetSales].[ExtendedAmount],[dbo].[FactInternetSales].[UnitPriceDiscountPct],[dbo].[FactInternetSales].[DiscountAmount],[dbo].[FactInternetSales].[ProductStandardCost],[dbo].[FactInternetSales].[TotalProductCost],[dbo].[FactInternetSales].[SalesAmount],[dbo].[FactInternetSales].[TaxAmt],[dbo].[FactInternetSales].[Freight],[dbo].[FactInternetSales].[CarrierTrackingNumber],[dbo].[FactInternetSales].[CustomerPONumber]
        FROM [dbo].[FactInternetSales]
                                WHERE OrderDateKey &gt;= '20070101' and  OrderDateKey &lt;= '20071231'</QueryDefinition>
            </Source>
            <StorageMode>Molap</StorageMode>
            <ProcessingMode>Regular</ProcessingMode>
            <ProactiveCaching>
                <SilenceInterval>-PT1S</SilenceInterval>
                <Latency>-PT1S</Latency>
                <SilenceOverrideInterval>-PT1S</SilenceOverrideInterval>
                <ForceRebuildInterval>-PT1S</ForceRebuildInterval>
                <AggregationStorage>MolapOnly</AggregationStorage>
                <Source xsi:type="ProactiveCachingInheritedBinding">
                    <NotificationTechnique>Server</NotificationTechnique>
                </Source>
            </ProactiveCaching>
            <EstimatedRows>1013</EstimatedRows>
            <AggregationDesignID>Internet Sales 1</AggregationDesignID>
        </Partition>
    </ObjectDefinition>
</Create>
The nodes, elements and attributes of the create partition XMLA command will form the metadata of the data-driven model as shown below.
SSASPartition
DatabaseIDSSAS database ID. Not name
CubeIDCube ID. Not name
MeasureGroupIDMeasure group ID. Not name
PartitionIDPartition ID. Not name
Partition NamePartition Name
PartitionSourceTypeQuery Binding, Table Binding
DataSourceIDData source ID
PartitionQuerySQL query of partition. Take note that SQL operators >,>=,< and <= have to be replaced with their html equivalents
  • &gt is html equivalent of >
  • &gt;= is html equivalent of  >= 
  • &lt is html equivalent of <
  • &lt;= is html equivalent of <=
StorageModeMolap, Rolap, Holap
ProcessTypeProcessData, ProcessFull, ProcessDefault, ProcessIndex
AggregationDesignIDAggregation Design ID. Null if aggregation design is not used
EstimatedRowsNull if aggregation design is not used
RequiresProcessFlagFlag=1 – partition requires data refreshFlag=0 – partition already processed and in refreshed state
CreatedDateTimePartition created timestamp. Null if partition is yet to be created
LastProcessedDateTimePartition last processed timestamp. Null if partition is yet to be processed
Populate this table with new partitions. Take note that Database ID, Cube ID, Measure Group ID and Partition ID may not be same as their corresponding names (for instance if the objects are renamed after they are first deployed) although in most instances they are same. Besides creating new partitions, this table also stores information to dynamically process the new and existing partitions.

Create Partition XMLA Command

Next step is to generate the XMLA command that creates partition. The following stored procedure uses FOR XML and XMLNAMESPACES to generate the XMLA command for each partition.
create procedure getPartitionCommand
     @DatabaseID as varchar(50)
    ,@CubeID as varchar(100)
    ,@MeasureGroupID as varchar(50)
    ,@PartitionID as varchar(500)
    ,@PartitionCommand as varchar(max) output
as
begin
    declare @ParentObjectXmla as varchar(max),@PartitionXmla  as varchar(max)
 
        select @ParentObjectXmla =
        (
        select @DatabaseID as DatabaseID, @CubeID as CubeID, @MeasureGroupID as MeasureGroupID
        for xml path ('ParentObject')
        );
 
 
        with xmlnamespaces('http://www.w3.org/2001/XMLSchema' as xsd
                            ,'http://www.w3.org/2001/XMLSchema-instance' as xsi
                            )
        select @PartitionXmla =
        (
        select PartitionID as ID
             , PartitionName as Name
             , PartitionSourceType as "Source/@xsi:type"
             , DataSourceID as "Source/DataSourceID"
             , PartitionQuery as "Source/QueryDefinition"
             , StorageMode as StorageMode
             , 'Regular' as ProcessingMode
             ,'-PT1S' as "ProactiveCaching/SilenceInterval"
             ,'-PT1S' as "ProactiveCaching/Latency"
             ,'-PT1S' as "ProactiveCaching/SilenceOverrideInterval"
             ,'MolapOnly' as "ProactiveCaching/AggregationStorage"
             ,'ProactiveCachingInheritedBinding' as "ProactiveCaching/Source/@xsi:type"
             ,'Server' as "ProactiveCaching/Source/NotificationTechnique"
             ,EstimatedRows as EstimatedRows
             ,AggregationDesignID as AggregationDesignID
        from dbo.SSASPartition
        where DatabaseID =@DatabaseID
            and CubeID = @CubeID
            and MeasureGroupID = @MeasureGroupID
            and PartitionID = @PartitionID
            and CreatedDateTime is null
        for xml path ('Partition')
        );
 
        set @PartitionCommand=
        +@ParentObjectXmla
        +'<ObjectDefinition>'
        + @PartitionXmla
        + '</ObjectDefinition></Create>'
end
Take note to return the XMLA as output parameter instead of a record set (SELECT @PartitionCommand). If returned as record set, SQL Server implicitly converts the XMLA string into XML, which SSIS interprets as object data type instead of string. SSIS has limited operations for object data type and an object data type variable cannot be assigned to task expressions.

SSIS Package

Create a SSIS package as shown below in screen capture 1
Screen Capture 1 - SSIS Package to Create Partitions
Screen Capture 1 – SSIS Package to Create Partitions
a) The “Get Partitions to be created” SQL execute task gets the list of partitions to be created as record set.
Screen Capture 2 - Get partitions to be created
Screen Capture 2 – Get partitions to be created
b)The “For each new partition” is an ADO enumerator which loops through the list of partitions.
c) “Get Partition Command” is the Execute SQL task which calls the getPartitionCommand stored procedure and returns the create partition XMLA command.
Screen Capture 3 – Get Partition Command
d) “SSAS Execute DDL Task – Create Partition” is an Analysis Services Execute DDL Task that is configured to use the XMLA command returned by the stored procedure.
Screen Capture 4 – SSAS Execute DDL Task – Create Partition
The new partition is created and processed using Process Default option. It would require Process Data in next run.
e) Finally update the metadata table and set the processing flag so that the cube processing package can automatically include this partition for processing next time it runs.
Screen Capture 5 – Update SSASPartition Table

Download Source Code

The SSIS package and database objects used in this post can be downloaded from here

Related Posts

  • SSIS: Dynamic Processing of SSAS Partitions
  • SSIS Package to Process SSAS Cube
  • SSAS: Process Incremental – What it is & isn’t
  • No comments:

    Post a Comment