Forum Discussion
Performance Between Two Measures - How to make the slower one more performant?
Hi everyone,
I have two implementations of a measure, and both implementations create an intermediate table and use that table for a calculation. One implementation only uses DAX, and the other uses a table in the model acting as the intermediate table and then uses it for the same calculation as the former measure. The first implementation is significantly slower than the latter, and I'd like to know if there is something I can do to increase performance ideally to match the second implementation, as it is acceptably quick.
The first implementation's DAX is this:
The temporary table I mentioned earlier is the UNION seen in the SUMX call. This measure does what we want, but becomes unacceptably slow if we slice a visual by the 'Date Dimension', and that is because of the FILTER logic at the end of the CALCULATE call (I think).
This is an example of the correct output for a table of Running Balance sliced by Date.
The calculation is a running total, up to the end of the given month.
I tried a few things to remedy the performance issue, but none have worked so far. My first attempt was to put the UNION result in a variable, but that lead to the incorrect slicing by dates. The calculation was fast, though.
From here I tried changing how much I include in the variable to keep the speed but create the correct slicing by dates, but I didn't find a solution.
An alternate I created (the second measure) creates the intermediate table in the model, and uses that instead.
This calculates the correct slicing by date, AND is fast. But it isn't suitable for various reasons, namely that the intermediate table cannot have the same relationships to other tables the original table does, as the crossjoin duplicates many keys so that our one-to-many relationships won't work. It works for date slicing, but does not for slicing done by columns in any other tables. The first measure doesn't have that issue, and just uses the measure's parent table's relationships as expected.
Is there a way I can make the first solution more performant? The second measure is just an example of a quick measure, and less of an actual alternative. I was hoping Power BI Desktop would handle the variable table similarly to the model table, but that is not the case.
I did also try creating the running balance without using the intermediate table, but I wasn't able to get the calculation to work. This is a method used somewhere else in our organization so copying it was the recommended solution.
Here is the WeTransfer link that contains my report with the measures and data (it is where the pictures are from): https://we.tl/t-psTz6NEKBz
Any advice or help is appreciated.
3 Replies
- jdbuchanan71
Super User
Just a question about what you are trying to accomplish.
Doesn't this section of the code:
CROSSJOIN( CALCULATETABLE( '*ACM Cylinder History', '*ACM Cylinder History'[Date/Time - Last Modified] <> BLANK() ), DATATABLE( "Quantity", INTEGER, { {-1}, {1} } ) ),
Always return a 0? You are summing the [Quantity] which, for every row where the'*ACM Cylinder History'[Date/Time - Last Modified] <> BLANK() is both 1 and -1 which makes the SUM 0 right?
When I tested this codeRunning Balance New = CALCULATE ( SUMX ( '*ACM Cylinder History', 1 ), '*ACM Cylinder History'[Date/Time - Last Modified] = BLANK (), REMOVEFILTERS ( 'Date Dimension' ), REMOVEFILTERS ( '*ACM Cylinder History'[Date - Transaction] ), FILTER ( CALCULATETABLE ( RELATEDTABLE ( 'Date Dimension' ), ALL () ), ISONORAFTER ( 'Date Dimension'[Date], MAX ( 'Date Dimension'[Date] ), DESC ) ) )
I get the same results as your original but it is much faster.
A table with the date and just the [Running Balance New] calcs in around 100 - 120 ms- AnthonyMCUBIFrequent Visitor
Hi jdbuchanan71,
You are correct, that will always equal 0. That is a bug in my DAX code, and I realize that fixes it complicates the measure further. The correct forumla goes as follows:
IF [Date/Time - Last Modified] <> BLANK()
THEN
IF Quantity = 1
THEN[Date/Time - Date Dimension Key] = [Date/Time - Last Modified]
ELSE
[Date/Time - Date Dimension Key] = [Date/Time - Modified]
ELSE
[Date/Time - Date Dimension Key] = [Date/Time - Modified]
The reason there are these conditions are because the table contains rows from two different sources, and the dates mean slightly different things.
Regardless, that is the formula so if it was correct then I don't think your simplification will work. Thinking about how to express the above in DAX...Thank you,
Anthony
- jdbuchanan71
Super User
Sorry, it's not really clear to me where you want to incorporate the fix. Are you saying that should be a column on the '*ACM Cylinder History' table then you join that one into your 'Date Dimension' table?