3
votes

Has anybody ever ported a complex ssas multidmensional cube to iccube? and have any advice to offer on lessons learnt/gaps between the two tools etc?

The major one i can see is scope(). What's the equivalent in iccube? nested if/case statements?

I have a list here. Anything else?

        function        |          SSAS          |         iccube     
------------------------|------------------------|------------------------
multi threaded calcs    | no                     | yes
------------------------|------------------------|------------------------
fix/scope block code    | SCOPE()                | ??
------------------------|------------------------|------------------------
custom functions        | clr.net but it's slow  | mdx+
------------------------|------------------------|------------------------
generic date utility    | third-party code that  | ??
dimensions (eg generic  | uses scope() eg        |
prior period/prior      | datetool               | 
corresponding period)   |                        |
------------------------|------------------------|------------------------

We have a very mdx script calculation heavy cube, and the single threaded nature of the SSAS calculation engine is a real bottleneck. None of the other olap tools we've looked at have been fast enough or had a rich enough language

We use disconnected utility dimensions to drive the functionality, and need to have a date utility dimension (we use a version of this http://sqlmag.com/sql-server-analysis-services/optimizing-time-based-calculations-ssas), use AXIS() extensively, and have recursive sum product across descendents of a hierarchy for a non-additive measure.

Our cube isn't a self service reporting cube. It's a multidimensional calculation engine for our app with a fixed generic schema


Update 1: A simpler example of how we use scope. ic, You mention 'robust' workarounds exist. What would they be for code like this?

// Assumes the date utility dim has been setup as with the priorperiod function as [Dim Date Calculations].[Date Calculations].[Prior Period]

// DimBenchmark is a single attribute disconnected utility dimension. The initial/default value is DimBenchmark.Benchmark.None ie do nothing. The remainder are dynamically set based on code. hardcoded below for simplicity
Scope(DimBenchmark.BenchMark.PriorPeriod);
    THIS = [Dim Date Calculations].[Date Calculations].[Prior Period]; // assign the value of some physical and utility dim members to new benchmark attributes. Allows us to only refer to dimbenchmark in subsequent code, irrespective of number of benchmarks or the src dimension.attribute
END SCOPE;

SCOPE(DimBenchmark.BenchMark.Budget);
    THIS = DimScenario.Scenario.Budget; //we also have a budget
END SCOPE;
.... // any number of other benchmarks

Create measure currentcube.measures.ComplexCalc as NULL;

SCOPE (measures.ComplexCalc); // this code will only change how complex calc behaves
    SCOPE (DimBenchmark.Benchmark.All - DimBenchmark.Benchmark.None); // this will only change the ComplexCalc when the active benchmark selection is not "none"
        this= (some measure,Complex subcube etc);
    End Scope;
End Scope;

the benefit of this is that complexcalc is null by default. it only gets a value when it meets specific conditions. the main reason to use scope is for speed. Much faster than if/case blocks (and simpler understand) i dont need to explicitly define which benchmarks are valid, just which benchmark isn't.

and below is how we've implemented the date utility dimension. It allows us to do something like (measure,[Dim Date Calculations].[Date Calculations].[Prior Period]) and it gives use the prior period of measure for the current member of dim date (month goes back 1 month, quarter goes back 3 months, semester goes back 6 mo, year goes back 12 mo). It's very clean, accurate and pretty fast.

-- Fiscal Month
Scope( [Dim Date].[Month Key].[Month Key].members);        
    -- Prior Period
    Scope([Dim Date Calculations].[Date Calculations].[Prior Period]);        
        this  =    
        ( [Dim Date].[Month Key].CurrentMember.PrevMember
         ,[Dim Date Calculations].[Date Calculations].[Current]
        );        
    END scope;                                       
End Scope;        


-- Fiscal Quarter
Scope( [Dim Date].[Fiscal Quarter].[Fiscal Quarter].members);        
    -- Prior Period
    SCOPE( [Dim Date Calculations].[Date Calculations].[Prior Period]);        
        THIS = ( [Dim Date].[Fiscal Quarter].CurrentMember.PrevMember
         ,[Dim Date Calculations].[Date Calculations].[Current]
        );        
    END SCOPE;                      
END SCOPE;        

-- Fiscal Semester
Scope( [Dim Date].[Fiscal Semester].[Fiscal Semester].members);        
    -- Prior Period
    SCOPE( [Dim Date Calculations].[Date Calculations].[Prior Period]);        
        THIS = ( [Dim Date].[Fiscal Semester].CurrentMember.PrevMember
         ,[Dim Date Calculations].[Date Calculations].[Current]
        );        
    END SCOPE;                                 
End Scope;        

-- Fiscal Year
Scope( [Dim Date].[Fiscal Year].[Fiscal Year].members);                     
    -- Prior Period
    SCOPE( [Dim Date Calculations].[Date Calculations].[Prior Period]);        
        THIS =    
        ( [Dim Date].[Fiscal Year].CurrentMember.PrevMember
         ,[Dim Date Calculations].[Date Calculations].[Current]
        );        
    END SCOPE;                  
End Scope;
1

1 Answers

2
votes

[disclaimer I'm working for icCube]

Scope is not part of icCube, not yet planned. It's a tricky feature that didn't naturally fit into icCube's architecture (see discussion below, later ... ). The strength of icCube is also the agility of it's R&D team, do not hesitate to contact them directly they will me more than happy to improve and add features.

In icCube there are some functionalities that are different from classical MDX server that might be useful, it's Categories, SubCubes and the eval function.

Categories. Allows for defining a new member that behaves like classical members. This new member can be defined as a set of members or as a subcube. For example here we can define a [Top10] category member as our 10 most important customers :

 CATEGORY MEMBER [Top10] as TopCount( [Customers], 10, ([Measures].[Sales],[2015]) )

 -> so later on ( [Top10], [Sales] ) will return the sales of this top10 customers

SubCubes, allows defining richer logical relations on members as a set of tuples. icCube implements SubCubeComplement, SubCubeIntersect,SubCubeOthers, SubCubeSymDifference, SubCubeUnion and SubCubeMinus. So calculating all without France (it's trivial here, but think on hierachies with many-to-many relations)

  SubCubeMinus([Geography].[Geo].[All], [Geography].[Geo].[France] )

The Eval function, allows for evaluating an expression on a subCube. Here is a trivial example doing the sum using the union :

 MEMBER [US+CH] AS Eval( SubCubeUnion( [Switzerland], [United States]) , [Amount])

Last but not least, for the dates function you can define Function in icCube that you can reuse in your MDX, no need to copy&paste everywhere :

 CREATE FUNCTION square( Value val ) AS val * val

and combine with CompactSet for a faster evaluation on dates periods (if there are no m2m relations on this dimension) or call some Java functions (you've to activate this module that is off by default).

--------------------- Scope ---------------------------

Warning : Comments might be obsolete as my understanding of scope is the one of a few years ago. Let's go :

Scope is a nice functionality but there are some drawbacks that you can check in Chris Webb's presentation ( link ), check from 47:30 for about 5 minutes.

The issues where/are :

Somehow a scope allows to define a new value for a subcube (remember a subcube might be a single indivisible cell as well as thousands of them)

1) Scopes allows for defining the value of a subcube but what do you do if you want a 'part' of this subcube ?

2) What happens if two scopes collide (intersection is not empty) ?

And all this mixed with security, many-to-many relations, subqueries and set where clauses.

We're not SSAS specialist and it's possible that with a better understanding we try again to implement a clean solution but for know we believe there are other ways solving the problems (for example using calc. members or writebacks).

hope it helps.