“Multi-threading” the Sql Server Analysis Services Formula Engine – I #ssas #mdx
October 4, 2012 2 Comments
The SSAS single threaded Formula Engine (FE)
It’s a known (also unfortunate…) fact that analysis services (multidimensional) formula engine (FE) is single threaded.
Now, for anyone not familiar with SSAS this should come as a very unusual limiting factor. Honestly, in a world dominated by the cloud, map/reduce, MPP/shared nothing platforms, (imo) the only plausible reason to still have a single threaded SSAS FE, is that we are really looking at an amazing product from a group of amazing minds that, unfortunately, hasn’t got any major upgrade since its very first 2005 release. (aside from 2008 block computation improvements ), and yes the reason for that reason would need another kind of post…
Well, not really single threaded…
A relevant note nevertheless is that, when we say SSAS FE is single threaded, we’re not talking about a single threaded engine FE per server, where we would have a single thread handling all session queries. That would be obviously unsustainable. What seems to happen -as far as I can guess- is that the FE is single thread per query. When the work is heavily FE bounded, a single thread will handle the FE load. Other simultaneous queries will get their own FE thread from the thread pool. (note: the number of total available worker threads is not unlimited of course)
A very simple query will show this behavior a (using with clause to inhibit the FE cache –a tip from Chris I use a lot – and median calculation to make it very CPU/FE bound):
with
member [Measures].[Test1] as
‘median([Customer].[Customer].[Customer],[Measures].[Internet Sales Amount])’
member [Measures].[Test2] as
‘median([Customer].[Customer].[Customer],[Measures].[Internet Tax Amount])’
member [Measures].[Test3] as
‘median([Customer].[Customer].[Customer],[Measures].[Internet Order Quantity])’
select
non empty {[Measures].[Test1],[Measures].[Test2],[Measures].[Test3] } on 0,
non empty [Date].[Calendar].[Month]*[Product].[Category].[Category] on 1
from [Adventure Works]
This query running on my laptop (SQL 2012 SSAS) will average 45-55 secs duration, with a very constant 20%-25% cpu usage (4 listed cores):
In a multi-core server environment this would be even more noticeable, with very low total cpu% usage during that query FE execution.
The real issue (for end users at least) is that adding more cores/cpus will not have any significant performance improvement for queries like this –but faster cpus should help a bit-. A single thread will handle all the load, all the cpu% power on recent hardware will be completely wasted. You will see several FE heavy queries taking several seconds to complete, almost without any kind of cpu/io pressure. “Uncomfortable” to watch at least.
“Partitioning” MDX queries & multi threading
If a “final round” can be expected for SSAS multidimensional I really hope that this could be somehow fixed (configurable at least), in a way that multiple threads could handle the FE load when appropriate.
(relevant update, see comments below, thanks Chris! don’t miss this post from Chris Webb, Parallelism and MDX Queries, an amazing piece of work using ssas proc/clr to multi thread some specific query patterns, may be this can be fine tuned for a wider range of scenarios)
Partitioning the workload by unrelated measure makes for a very strong candidate. (related measures will share intermediate calculations,cache, and probably won’t benefit so much from multi threading).
An example, let’s split that previous query into three, one for each measure requested, (note that I used 3 unrelated base measures)
(query 1, the others are similar)
Executing them in parallel will result in something like: query1: 24 secs, query2: 23 secs, query 3: 23 secs. But as they executed simultaneously, we only have to wait for the longest one to get all the data we need, ~24 secs. Less 50% of the original single query duration.
CPU usage now spikes predictably to ~75% during the ~25 secs queries duration.
Possible scenarios for query partitioning
So, what do we take from here? Well, it depends a lot on each specific query workload… But it can come handy in some scenarios:
- you have a system were cpu capacity is clearly underused most of time
- you control the queries sent to ssas, through a web frontend for example or you are using a frontend that can use multiple parallel requests (tip: performance point)
- queries are easy “partitionable“, eg: by measure
- you already did everything possible regarding the usual ssas performance tuning best practices (at least everything -you think- is possible)
In these scenarios, you can try to partition the queries, execute and aggregate the results. There’s a chance that your users can benefit from better response times.
(and of course partitioning queries like this is a poor solution for badly written MDX that tends to be very FE intensive. For that my recipe is always refer back to Chris, Marco, Mosha, Piasevoli, Greg, Kasper, Richard, and many others, never forgetting our amazing BI team at DevScope :) )
Next post: “Multi-threading” the Sql Server Analysis Services Formula Engine II – Performance Point
Stay tuned!
Rui