![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
Could somebody explain why the first query below is significantly faster than the second query. When I say faster, I'm talking 1 second versus a few minutes. The only differences are the way the WITH MEMBER section is built up, so I haven't included the full query. The Source and Destination dimension has 300 members on it (001 to 300). The slow query below is physically a much longer query when you expand the "etc etc" parts below so don't be deceived by its short length below. The result produced for [SOURCE].[Slicer] and [DESTINATION].[Slicer] should be exactly the same in both queries. So why does the way it is expressed (or built-up) matter? This should only make a split second difference. Fast Version of Query: WITH MEMBER [SOURCE].[Slicer] AS '[SOURCE].[ALL SOURCE] - ([SOURCE].[298] + [SOURCE].[299] + [SOURCE].[300])' MEMBER [DESTINATION].[Slicer] AS '[DESTINATION].[298] + [DESTINATION].[299] + [DESTINATION].[300]' Slow Version of Query: WITH MEMBER [SOURCE].[Slicer] AS '[SOURCE].[001] + [SOURCE].[002] + {etc etc} + [SOURCE].[297]' MEMBER [DESTINATION].[Slicer] AS 'SUM(DESTINATION.DESTINATION.MEMBERS) - ([DESTINATION].[001] + [DESTINATION].[002] + {etc etc} + [DESTINATION].[297])' |
#3
| |||
| |||
|
|
Almost certainly because in the first query, when you request the value for [Source].[All Source] you are hitting an aggregation, so that it doesn't need to be computed at runtime. That then means that the first query only does a fraction of the work that the second does. |
#4
| |||
| |||
|
|
"Chris Webb" <OnlyForPostingToNewsgroups (AT) hotmail (DOT) com> wrote in message news:7EBAC267-915E-47C7-8D4F-B3E0F7C82902 (AT) microsoft (DOT) com... Almost certainly because in the first query, when you request the value for [Source].[All Source] you are hitting an aggregation, so that it doesn't need to be computed at runtime. That then means that the first query only does a fraction of the work that the second does. I didn't expect the cube to evaluate the query this way...but I guess it makes sense. The problem I have now is if you allow the user to pick a bunch of source locations (eg. 100 source locations) and the unselected locations become destination locations, a massive query is generated. This query takes many minutes to execute. SQL Server seems to do a more efficient job at grouping/filtering the data. If I was to express the problem in SQL, it would be similar to this (the user selected locations 001 to 297, there are 12 months of data): SELECT Month, Sum(MyMeasure) FROM MyTable WHERE Source IN ('001', '002', '003' .... '297') AND Destination NOT IN ('001', '002', '003' .... '297') GROUP BY Month It doesn't take too long to run in SQL Server. The cube takes forever to do this job. How can you create a well designed cube or query to optimise this? Thanks, Charlie |
#5
| |||
| |||
|
|
Without thinking of any other kinds of optimisation, my first shot at such a query would look something like this: WITH SET MYSOURCES AS '{[SOURCE].[001], [SOURCE].[002],... ETC}' SET MYDESTS AS 'EXCEPT( [DESTINATION].[DESTINATION LEVEL].MEMBERS, GENERATE(MYSOURCES, LINKMEMBER([SOURCE].CURRENTMEMBER, [DESTINATION])) )' MEMBER [SOURCE].SLICER AS 'SUM( NONEMPTYCROSSJOIN(MYSOURCES, MYDESTS) )' SELECT MEASURES.MEMBERS ON 0, [MONTHLYTIME].MEMBERS ON 1 FROM MYCUBE WHERE([SOURCE].SLICER) |
|
Also, I know that someone else mentioned this earlier, but using Execution Location=3; Default Isolation Mode=1 in your connection string to try to push query execution to the server would be a good thing to try too, as would |
#6
| |||
| |||
|
|
"Chris Webb" <OnlyForPostingToNewsgroups (AT) hotmail (DOT) com> wrote in message news:5290F380-4353-4C32-B5B7-C53BB8D62B9F (AT) microsoft (DOT) com... Without thinking of any other kinds of optimisation, my first shot at such a query would look something like this: WITH SET MYSOURCES AS '{[SOURCE].[001], [SOURCE].[002],... ETC}' SET MYDESTS AS 'EXCEPT( [DESTINATION].[DESTINATION LEVEL].MEMBERS, GENERATE(MYSOURCES, LINKMEMBER([SOURCE].CURRENTMEMBER, [DESTINATION])) )' MEMBER [SOURCE].SLICER AS 'SUM( NONEMPTYCROSSJOIN(MYSOURCES, MYDESTS) )' SELECT MEASURES.MEMBERS ON 0, [MONTHLYTIME].MEMBERS ON 1 FROM MYCUBE WHERE([SOURCE].SLICER) This query seems to take about 2-3 seconds to execute regardless of how many locations are selected. This is very acceptable, so thanks for suggesting it. Also, I know that someone else mentioned this earlier, but using Execution Location=3; Default Isolation Mode=1 in your connection string to try to push query execution to the server would be a good thing to try too, as would I've already tried using server-side execution, and it does seem to offer a modest performance gain. I will consider your other suggestions too but for now the query above was a great help and probably all I needed. Thanks, Charlie |
![]() |
| Thread Tools | |
| Display Modes | |
| |