MDX Calculated Member Performance Issue - ssas

SELECT NON EMPTY {
[Measures].[Production_Volume]
} ON COLUMNS,
NON EMPTY { (
[Make].[Make ID].[Make ID].ALLMEMBERS
* [Model].[Model Hierarchy].[MDL].ALLMEMBERS
* [Customer].[Customer ID].[Customer ID].ALLMEMBERS
) } ON ROWS
FROM [Model_Cube]
This query is taking 10 min
[Measures].[Production_Volume] is a calculated member in the cube, if I put the definition of this member directly in the query it's taking much lesser time.
WITH MEMBER [Measures].[Production_Volume] AS
([Measures].[Model Count],
([Status].[Status Type].&[T]
,[Mode].[Mode Type].&[A])
)
+ Sum(
([HYBRID_MODELS]
,[Status].[Status Type].&[C]
,[Mode].[Mode Type].&[A])
,[Measures].[Model Count]
)
SELECT NON EMPTY {
[Measures].[Production_Volume]
} ON COLUMNS,
NON EMPTY { (
[Make].[Make ID].[Make ID].ALLMEMBERS
* [Model].[Model Hierarchy].[MDL].ALLMEMBERS
* [Customer].[Customer ID].[Customer ID].ALLMEMBERS
) } ON ROWS
FROM [Model_Cube]
this query is taking 4 sec
Unable to understand the difference between the two, I ran the profiler but couldn't find any difference, except that the first query showed flight recorder snapshot events second query didn't.

The problem was how I created named sets "[HYBRID_MODELS]". I changed them from DYNAMIC to STATIC this helped. Another change I did was replace -{} with the EXCEPT() function. These both changes reduced query time from 30min to 1min!
Hope this helps someone in need :)

Related

Simple Calculated Member Running for Forever - MDX

I am facing very strange issue with MDX (SSAS 2014), on which simplest calculated member is taking forever to execute. Could someone please help me to understand why i am facing this issue. If i not use calculated member everything works fast and result comes in seconds. When i remove Producer attribute, query performances well.
Below is the complete query.
WITH
MEMBER Measures.AsOfDate AS ("[Policy Effective Date].[Year-Month].[Date].&[2018-01-04T00:00:00]")
MEMBER Measures.YTDPremium AS AGGREGATE (YTD(STRTOMEMBER(Measures.AsOfDate)), [Measures].[Written Premium])
SELECT NON EMPTY
{
Measures.YTDPremium
} ON COLUMNS, NON EMPTY
{
(
[Program].[Program Name].[Program Name]
,[Insuring Company].[Insuring Company Name].[Insuring Company Name]
,[Line Of Business].[Line Of Business].[Line Of Business]
,[Producer].[Producer Name].[Producer Name]
)
} ON ROWS
FROM [Premium]
Try understand what the following part does in your query
NON EMPTY { ( [Program].[Program Name].[Program Name]
,[Insuring Company].[Insuring Company Name].[Insuring Company Name]
,[Line Of Business].[Line Of Business].[Line Of Business]
,[Producer].[Producer Name].[Producer Name]
) } ON ROWS
In the above MDX you are telling the server to take a cross product of all values of "Programs", "Line Of Business" and "Producer Name". So lets say you have 4 values of programs , 3 values of line of business and 2 values of producer name. The total combinations are 4*3*2=24
Now the "Non empty" removes any combinations that are not present in your dataset. This is done by removing all rows that have "Null" value in column value.
Your measure is returning value irrespective if that combination exists or not. You can modify your Calculatedmeasure to return value only in the case if the combination is valid. This can be achived by checking an actual measure for that combination
Edit: based the below example is based on the comment
In the below example i am trying to get the internet sales amount categories and components
select
{ [Measures].[Internet Sales Amount] }
on columns,
(
[Product].[Category].[Category],
[Customer].[Country].[Country]
)
on rows
from [Adventure Works]
Result
Now add "Non empty" to the query and observe the results.
Results
Now lets add calculted measure that returns "hello". Notice how the non empty clause is ineffective.
Now modify the code make the calculated measure check other measures for null
with member measures.t as
case when [Measures].[Internet Sales Amount] = null then null else "hello" end
select
{ [Measures].[Internet Sales Amount] ,measures.t }
on columns,
non empty
(
[Product].[Category].[Category],
[Customer].[Country].[Country]
)
on rows
from [Adventure Works]
Result
The bottom line: Because of cross product your result is so huge that SSAS is having hard time handling it.

MDX query returning duplicate rows in SSAS tabular mode cube

I'm completely new to SSAS cubes and terminologies (members, hierarchies, e.t.c) and MDX queries but i have started my journey to learn this stuff, so apologies if my question is very clear.
SELECT NON EMPTY { } ON COLUMNS, {
[Suggestions].[Parent_id].[Parent_id] *--.ALLMEMBERS *
[Suggestions].[id].[id] * --.ALLMEMBERS *
[Suggestions].[Sugg - #].[Sugg - #] *-- .ALLMEMBERS *
[Suggestions].[Sugg - Assigned].[Sugg - Assigned] * --.ALLMEMBERS *
[Suggestions].[Sugg - Assigned to].[Sugg - Assigned to]* --.ALLMEMBERS *
[Suggestions].[Sugg - Status].[Sugg - Status] *--.ALLMEMBERS
--[Parent_Details].[Unit_Name].[Unit_Name] --.ALLMEMBERS
}
DIMENSION PROPERTIES MEMBER_CAPTION,
MEMBER_UNIQUE_NAME ON ROWS
FROM ( SELECT ( { [Suggestions].[Sugg - Assigned to].&[UNIT] } ) ON COLUMNS
FROM ( SELECT ( STRTOSET('SG123', CONSTRAINED) ) ON COLUMNS
FROM ( SELECT ( { [Suggestions].[Sugg - Status].&[Pending Inputt] } ) ON COLUMNS
FROM [BOI_Tracker-Stats])))
CELL PROPERTIES VALUE
I have the above MDX query that executing. I generated the query from the MDX query designer tool in SSMS and have only simple modifications by hand.
In the query, if i comment out the line [Parent_Details].[Unit_Name].[Unit_Name] --.ALLMEMBERS, i get the correct number of rows.
Main Question.
If i un-comment it so that i return the Unit_Name column, my rows are duplicated. The original 100 correct rows now because thousands of rows with duplicate values all over. Any body know what i should look out for that is causing this. Looks a wrong join is being applied.
Other things i would like to understand.
1. The query designer generated the query in the format
[Suggestions].[Parent_id].[Parent_id].ALLMEMBERS * . If i comment out .ALLMEMBERS * such that the query is just [Suggestions].[Parent_id].[Parent_id] with out .ALLMEMBERS * the results are the same. So what is the use of .ALLMEMBERS *
2. I also notice that the column i want to select is repeated twice like
Suggestions].[Parent_id].[Parent_id], why is this so?, why can't it just be generated as Suggestions].[Parent_id]
If you select from different dimensions like that you basically multiply the results. If you think about it that's the correct behavior. In your case you have [Suggestions] and [Parent_Details] . These are different dimensions. In your query you want results having both so it does:
For each member of [Suggestion] get all members of [Parent Details] and add them to the result. So the result set becomes:
[Suggestion-1][Parent_Details-1][Measures...]
[Suggestion-1][Parent_Details-2][Measures...]
[Suggestion-2][Parent_Details-1][Measures...]
[Suggestion-2][Parent_Details-2][Measures...]
[Suggestion-3][Parent_Details-1][Measures...]
etc.
( having different levels from the [Suggestions] dimension doesn't multiply the measures )
This is a correct behavior when you think about it because if you add these two dimensions you probably want to know something like "What are the measures for that suggestion and for these parent details?" And that exact row will be correct in the result set. It all depends on what result do you want to get (What do you ask for).
The multiplication of the names depends on your cube design. First row is a level and second a member. If you create a hierarchy for example it will not look like that.

mdx calculated measure versus measure

just wondering if you could explain to me why these two mdx statements yield different results, and how I would alter the calculated measure to be correct. I am assuming the calculated measure is incorrectly using the sum function.
SELECT
{
[Measures].[PPPH]
}
ON COLUMNS,
{
[Matter].[Parent Matter Lawyer - Responsible].&[qnas]
}
ON ROWS
FROM [Expert Hypercube]
WHERE
(
[Date].[Fiscal].[Month].&[201702],
[Relative Period].[Relative Period].&[YTD]
)
versus
with
member measures.[PPPHx] as
sum({{linkmember([Timekeeper].[Person].currentmember,[Matter].[Parent Matter Lawyer - Responsible])}},measures.[PPPH])
select
{
measures.[PPPHx]
} on columns,
{
[Timekeeper].[Person].&[qnas]
} on rows
from [Expert Hypercube]
where
(
[Date].[Fiscal].[Month].&[201702],
[Relative Period].[Relative Period].&[YTD]
)
It's unclear why do you use Sum function at all. LinkMember function returns a member, no need to cover it with {...} like a set. Also you need to use the All member, since it returns [Timekeeper].[Person].CurrentMember + LinkMember([Timekeeper].[Person].CurrentMember,[Matter].[Parent Matter Lawyer - Responsible]).
With
Member [Measures].[PPPHx] as
(
LinkMember([Timekeeper].[Person].CurrentMember,[Matter].[Parent Matter Lawyer - Responsible]),
[Timekeeper].[Person].[All],
[Measures].[PPPH]
)
See a Richard Lees's article about it.

Aggregation on different level of dimension hierarchy

I have two dimensions, lets say Date Hierarchy and Product and a measure which has MAX (Measures.[Max]) aggregation.
The requirement would be to have SUM of Measures.[Max] on DAY or HOUR level of Date Hierarchy and be summarized in Month level.
I have the following query:
With
Member Measures.SumOfMax as SUM([Date].[Hierarchy].[Hour].AllMembers, Measures.[Max])
Select
NON Empty
{
Measures.SumOfMax
} ON COLUMNS,
NON EMPTY
{
[Date].[Hierarchy].[Month].AllMembers *
[Product].[Product Name].[Product Name].Allmembers
} Having Measures.[Max] > 0
ON ROWS
FROM [Cube]
Above query runs very slow. Are there any ways to optimized this?
The problem with this query is that the calculated measure Measures.SumOfMax is evaluated for every cell on the axis although it's yielding the same value each time. SSAS engine is not intelligent enough to understand that, but since you know about this behavior, you can take advantage of FE caching so that it gets evaluated only once and gets cached in FE cache. Read more on it here
With
Member Measures.[_SumOfMax] as SUM([Date].[Hierarchy].[Hour].AllMembers, Measures.[Max])
Member Measures.[SumOfMax] as ([Date].[Hierarchy].[Hour].[All], Measures.[_SumOfMax])
Select
NON Empty
{
Measures.SumOfMax
} ON COLUMNS,
NON EMPTY
{
[Date].[Hierarchy].[Month].AllMembers *
[Product].[Product Name].[Product Name].Allmembers
} Having Measures.[Max] > 0
ON ROWS
FROM [Cube]
Hope this helps.

Easiest way to programmatically generate MDX rowcount query?

Right now I'm dealing with a program that can generate and return SQL or MDX queries (depending on the source database of the queries). I'm working on adding a feature that counts all the rows returned by a given query.
Now, I have some small background with SQL, so I was able to parse table names and generate a rowcount. However, MDX is a completely new beast for me.
In SQL, I'm creating:
SELECT
COUNT(SUM)
AS ROWS
FROM
(
COUNT(*) AS COUNT FROM TABLE1
UNION ALL
COUNT(*) AS COUNT FROM TABLE2
UNION ALL
COUNT(*) AS COUNT FROM TABLE3
ETC...
)
Now, what I'm wondering is, how would I do something similar with MDX? I've done some reading on MDX, and from what I gathered the basic notation is
[Dimension].[Hierarchy].[Level]
Now with SQL, I parsed the table names out of a larger generated query and simply inserted them into a new programmatically generated query. What would I have to grab from a larger MDX query to generate my own rowcounting query and sending it off to run? A simpler example of the MDX I'm dealing with would be:
WITH
MEMBER [BUSINESS1].[XQE_RS_CM1] AS '([BUSINESS1].[COMPANY_H].[all])', SOLVE_ORDER = 8
MEMBER [BUSINESS2].[XQE_RS_CM0] AS '([BUSINESS2].[all])', SOLVE_ORDER = 4
SELECT
NON EMPTY {[BUSINESS2].[ALL_TIME_H].[CALENDAR_YEAR_L].MEMBERS AS [XQE_SA1] , HEAD({[BUSINESS2].[XQE_RS_CM0]}, COUNT(HEAD([XQE_SA1]), INCLUDEEMPTY))} DIMENSION PROPERTIES PARENT_LEVEL, PARENT_UNIQUE_NAME ON AXIS(0),
NON EMPTY {[BUSINESS1].[COMPANY_H].[COMPANY_CD__L].MEMBERS AS [XQE_SA0] , HEAD({[BUSINESS1].[XQE_RS_CM1]}, COUNT(HEAD([XQE_SA0]), INCLUDEEMPTY))} DIMENSION PROPERTIES PARENT_LEVEL, PARENT_UNIQUE_NAME ON AXIS(1),
NON EMPTY {[Measures].[Measures].[BUSINESS3]} DIMENSION PROPERTIES PARENT_LEVEL, PARENT_UNIQUE_NAME ON AXIS(2)
FROM
[SOURCE] CELL PROPERTIES CELL_ORDINAL, FORMAT_STRING, VALUE
Any insight would be awesome, thanks.
At first glance your script looks reasonable then after unravelling it becomes a bit(!) more complex.
The main difference between this and other scripts is its use of axis(2). In a sub-select extra dimensions are often used but this is a little odd as most clients can't handle 3 dimensional cellsets - so I'm intrigued by what is consuming this info?
Also the member [BUSINESS1].[XQE_RS_CM1] is a single member as is [BUSINESS2].[XQE_RS_CM0] so what is the point of the sections HEAD... ?
WITH
MEMBER [BUSINESS1].[XQE_RS_CM1] AS
([BUSINESS1].[COMPANY_H].[all]), SOLVE_ORDER = 8
MEMBER [BUSINESS2].[XQE_RS_CM0] AS
([BUSINESS2].[all]), SOLVE_ORDER = 4
SELECT
NON EMPTY
{[BUSINESS2].[ALL_TIME_H].[CALENDAR_YEAR_L].MEMBERS AS [XQE_SA1]
,HEAD(
{[BUSINESS2].[XQE_RS_CM0]},
COUNT(
HEAD([XQE_SA1])
,INCLUDEEMPTY
)
)}
ON AXIS(0),
NON EMPTY
{[BUSINESS1].[COMPANY_H].[COMPANY_CD__L].MEMBERS AS [XQE_SA0]
,HEAD(
{[BUSINESS1].[XQE_RS_CM1]},
COUNT(
HEAD([XQE_SA0])
,INCLUDEEMPTY
)
)}
ON AXIS(1),
NON EMPTY
{
[Measures].[Measures].[BUSINESS3]
}
ON AXIS(2)
FROM
[SOURCE]
Does the following return the same data as the original script?
SELECT
NON EMPTY
{
[BUSINESS2].[ALL_TIME_H].[CALENDAR_YEAR_L].MEMBERS
,[BUSINESS2].[all]
}
ON 0,
NON EMPTY
{
[BUSINESS1].[COMPANY_H].[COMPANY_CD__L].MEMBERS
,[BUSINESS1].[COMPANY_H].[all]
}
ON 1
FROM [SOURCE]
WHERE [Measures].[Measures].[BUSINESS3];
All you need to calculate then is the count of members returned in the following set on the rows:
{
[BUSINESS1].[COMPANY_H].[COMPANY_CD__L].MEMBERS
,[BUSINESS1].[COMPANY_H].[all]
}