【MDX学习笔记5】优化集合运算——SUM中的CrossJoin
墨初 知识笔记 69阅读
今天看了《MDX Solutions with Microsoft SQL.Server Analysis Services 2005 and Hyperion Essbase 2nd Edition》书中优化集合运算的内容,根据书中内容做了一些测试。测试结果有的符合书上的观点,有的却完全不同,真的很让人吃惊。书中优化集合运算的主要观点有:1。优化集合运算的关键是将大集合运算转化为小集合运算。2.由于CrossJoin的成本(CPU、内存)巨大,不如用其他操作代替CrossJoin操作。作者SUM中的CrossJoin认为:为了避免SUM,一个集合包含多个CrossJoin,可以用其他运算来代替它(比如嵌套SUM)。因此,我测试了两组语句:withmembermeasures。abcassum(交叉联接(后代([客户])。[客户地理位置]。当前成员,[客户]。
: rgba(0, 0, 0, 1)">.[Customer Geography].[State-Province]),
Crossjoin (
Descendants (
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Date]
),
Descendants (
[Product].[Product Categories].CurrentMember,
[Product].[Product Categories].[Product Name]
)
)
)
,[Measures].[Internet Sales Amount]-[Measures].[Internet Tax Amount]
)
SELECT MEASURES.ABC ON 0 ,
[Customer].[Customer Geography].[Country].Members *
[Date].[Calendar].[Calendar Year].MEMBERS *
[Product].[Product Categories].[Category].MEMBERS
ON 1
FROM [Adventure Works]
Sum (
Descendants (
[Customer].[Customer Geography].CurrentMember,
[Customer].[Customer Geography].[State-Province]
),
SUM(
Descendants (
[Product].[Product Categories].CurrentMember,
[Product].[Product Categories].[Product Name]
),
SUM(
Descendants (
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Date]
)
,[Measures].[Internet Sales Amount]-[Measures].[Internet Tax Amount]
)
)
)
SELECT MEASURES.ABC ON 0 ,
{[Customer].[Customer Geography].[Country].Members} *
[Date].[Calendar].[Calendar Year].Members *
[Product].[Product Categories].[Category].Members
ON 1
FROM [Adventure Works]
以上语句中,作者认为第一个语句慢于第二个语句(理由是嵌套的SUM每次操作的SET更小),可实际的结果(测了10次)恰恰相反,第一个语句平均花费的时间51.654秒,而第二个语句平均花费的时间在55.912秒,这是何故呢?此外,书中认为在第二个语句的嵌套SUM中,如果把大的Set放在里面,这样会快一些。也就是说下面的语句比上面第二个语句要慢5%-20%。

Sum (
Descendants (
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Date]
),
SUM(
Descendants (
[Product].[Product Categories].CurrentMember,
[Product].[Product Categories].[Product Name]
),
SUM(
Descendants (
[Customer].[Customer Geography].CurrentMember,
[Customer].[Customer Geography].[State-Province]
),
[Measures].[Internet Sales Amount]-[Measures].[Internet Tax Amount] )
)
)
SELECT MEASURES.ABC ON 0 ,
{[Customer].[Customer Geography].[Country].Members} *
[Date].[Calendar].[Calendar Year].Members *
[Product].[Product Categories].[Category].Members
ON 1
FROM [Adventure Works]
以上测试语句中,关于[Date].[Calendar].[Date]的Set其Turple个数在365左右,关于[Product].[Product Categories].[Product Name]的Set其Turple个数在几十个左右,而关于[Customer].[Customer Geography].[State-Province]的Set其成员个数大多在十几个左右
经过测试发现上面这条语句平均时间在57.858秒。也就是说,测试结果和书中的观点是一致的,只是幅度没有那么大。此外,我还尝试了一下这样的写法。
MEMBER MEASURES.ABC AS
Sum (
CrossJoin (
Descendants (
[Customer].[Customer Geography].CurrentMember,
[Customer].[Customer Geography].[State-Province]
),
Crossjoin (
Descendants (
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Date]
),
Descendants (
[Product].[Product Categories].CurrentMember,
[Product].[Product Categories].[Product Name]
)
)
) AS MYABC
,[Measures].[Internet Sales Amount]
)-
Sum (
MYABC
,[Measures].[Internet Tax Amount]
)
SELECT MEASURES.ABC ON 0 ,
[Customer].[Customer Geography].[Country].Members *
[Date].[Calendar].[Calendar Year].MEMBERS *
[Product].[Product Categories].[Category].MEMBERS
ON 1
FROM [Adventure Works]
上面语句的不同之处在于,把要计算的内容分散开来了,令人惊异的是,这个语句只要2-3秒种就能运行完成。
总结
由上面两次测试我们可以得出以下结论:
1)SUM中的CrossJoin并不一定会降低速度,书中的观点可能是错误的。看来MDX解析器对CrossJoin有很多有优化,在上面的测试中CrossJoin比嵌套的SUM要快8%左右。
2)嵌套SUM中,把大的SET放在里层的SUM中,这样速度能够快一些。上面的测试中,把小的Set放在里层比把大的Set放在里层慢3.5%。
3)在做SUM等统计计算时,如果能够把计算项分解到每个单独的Measure,这个时候性能提升非常明显,速度将会大大提高。上面的测试中,速度提高了20多倍。
