Tuesday, July 28, 2015

Using SSAS Formula Engine Cache with Non-Deterministic Functions

If you have complex MDX calculations which take long time to execute, you might be able to exploit formula engine (FE) cache and get good performance.

The following diagram from  “Microsoft SQL Server Analysis Services Multidimensional Performance and Operations Guide” gives overview of query processing.


If calculation results are available in formula engine cache, the values are returned immediately.

If calculation results are available in formula engine cache, the values are returned immediately.



The use on Non-Deterministic functions (e.g. Now() ),  causes FE cache to be not used. Instead, storage engine cache is used instead and calculations are re-evaluated.

As a work around, you can create a static named set using the Non-Deterministic function and use the named set in the calculation inside MDX script.

// Create Static Named Set.
CREATE SET CurrentCube.[Last Completed Month TY] as
(StrToMember("[Date of Service].[Calendar].[DateID].&[" + Format(DateAdd("d",-Day(Now()),Now()), "yyyyMMdd") + "]"));


// Use the named set in calculation.
CREATE MEMBER CURRENTCUBE.measures.[office visits new - ty]
 AS (
      [Measures].[Office Visits - New],
      [Date of Service Comparison].[Aggregation].[Year To Date] ,
      [Last Completed Month TY].Item(0)
),
VISIBLE = 1 ;  

The above calculation uses a date-tool dimension called “Date of Service Comparison” with a member “Year To Date”


// Using date-tool dimension.
SCOPE (
    [Date of Service].[Calendar].MEMBERS,
      [Date of Service].[DateID].MEMBERS );                                                      
   
    ///////////////////////////////////////////////////////////////////////////////////////
    [Date of Service Comparison].[Aggregation].[Year To Date]
          = Aggregate(
                     { [Date of Service Comparison].[Aggregation].DefaultMember } *
                       PeriodsToDate(
                                    [Date of Service].[Calendar].[Year Number],
                                    [Date of Service].[Calendar].CurrentMember
                     ) ); 
                    
END SCOPE;



Note: To use FE cache the calculations should be done in MDX Script in the cube, If the Calculations are done in MDX Query (using WITH Clause), they are re-evaluated every time.

To get the calculation results into FE cache, execute an MDX query which uses the calculation (after cube is processed).
SELECT measures.[My Complex Calculated Measure] FROM MYCUBE


Monday, July 6, 2015

T-SQL Date Calculations.


  -- Yesterday
  SELECT  CAST(GETDATE()-1 AS Date) AS Yesterday
 
  -- Beginning of Year
  SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) AS StartOfYear
  -- End of Year
  SELECT CAST(DATEADD(s,-1,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0)) AS Date) AS EndOfYear
 
  -- Beginning of Previous Year
  SELECT DATEADD(yy, DATEDIFF(yy,0,getdate())-1, 0) AS StartOfPreviousYear
  -- End of Previous Year
  SELECT CAST(DATEADD(s,-1,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) AS Date) AS EndOfPreviousYear

  -- Beginning of Month
  SELECT DATEADD(mm, DATEDIFF(m,0,GETDATE()),0) StartOfMonth
  -- End of Month
  SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)) AS Date) EndOfMonth
 
  -- Beginning of Previous Month
  SELECT DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0) StartOfPreviousMonth
  -- End of Previous Month
  SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) AS Date) EndOfPreviousMonth
 
  -- Rolling 12 Months. Begin.
  SELECT DATEADD(mm, DATEDIFF(m,0,GETDATE())-12,0) Rolling12MosBegin
  -- Rolling 12 Months End.
  SELECT CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) AS Date) Rolling12MosEnd



-- Using SQL Server 2012 EOMONTH Function


-- Beginning of Year
select DATEADD(DAY,1,EOMONTH ( getdate(), - month(getdate()) )) StartOfYear
-- End of Year
select EOMONTH ( getdate(), 12 - month(getdate()) ) EndOfYear

-- Beginning of Previous Year
select DATEADD(DAY,1,EOMONTH ( getdate(), - month(getdate()) -12 )) StartOfPreviousYear
-- End of Previous Year
select EOMONTH ( getdate(),  - month(getdate()) ) EndOfPreviousYear


-- Beginning of Month
select DATEADD(DAY,1,EOMONTH ( getdate(), -1 )) StartOfMonth
-- End of Month
select EOMONTH ( getdate() ) EndOfMonth


-- Beginning of Previous Month
select DATEADD(DAY,1,EOMONTH ( getdate(), -2 )) StartOfPreviousMonth
-- End of Previous Month
select EOMONTH ( getdate(),-1 ) EndOfPreviousMonth


-- Rolling 12 Months Begin
select DATEADD(DAY,1,EOMONTH ( getdate(), -13 )) Rolling12MosBegin
-- Rolling 12 Months End

select EOMONTH ( getdate(),-1 ) Rolling12MosEnd