Jonnas

专注数据库技术

博客园 首页 新随笔 联系 订阅 管理
 

概览

SQL Server 2005 Analysis Services 引入了一些新的MDX语法,从而提供了比同等的AS 2000的查询语句更好的性能。

下面列出了一些技巧,可以帮助在AS2005MDX查询中获得更好的性能

 

详细内容

 

  1. 先过滤,再做Crossjoin

首先过滤集合,然后在Crossjoin内使用。 Filter函数会物化整个集合并且轮训整个集合,然后用符合条件的元组建立一个新的集合。

 

避免:

filter(NECJ({set1},{set2}),..)

推荐:

NECJ(filter({set1},...),{set2})"

 

  1. 使用Rank()代替Intersect()检查集合中成员是否存在

Intersect的缺陷在于,它检查集合中成员的时候,将成员看做一个集合,这在求值过程中不能生成优化的执行计划

 

避免:

iif(intersect({ACTUALS_DAYS_SET},{[TIME DIM].[Time Main].currentmember}).count)>0

推荐:

iif(rank([TIME DIM].[Time Main].currentmember, {ACTUALS_DAYS_SET})>0

 

  1. 用大括号包含Crossjoin内部的单一成员

Crossjoin的时候总是使用集合,因此即使是单一的成员也要用大括号包含

 

避免:

Sum( [FINANCIAL VERSION DIM].[Financial Version].[Financial Version Type].&[WSLT]

*{[GROUP STATUS DIM].[Group Status].[Group Status Name].[cancel]

,[GROUP STATUS DIM].[Group Status].[Group Status Name].[turn down]},measure)

推荐:

Sum(

{[FINANCIAL VERSION DIM].[Financial Version].[Financial Version Type].&[WSLT]}

*{[GROUP STATUS DIM].[Group Status].[Group Status Name].[cancel]

,[GROUP STATUS DIM].[Group Status].[Group Status Name].[turn down]},Measure)

 

  1. 计算成员中避免不必要的 .CurrentMember

添加不需要的 .CurrentMember不是一个好习惯。如果在MDX中不适用 "CurrentMember"来获取维度的当前成员,可以让计算引擎生成一个更好的查询计划。CurrentMember是隐式的(默认),不需要显式包含在查询中

 

下面的MDX[TIME DIM].[Time Main].[Year].currentmember 是没用的

 

WITH

MEMBER [Measures].[M] as

'([TIME DIM].[Time Main].[Year].currentmember

,[FINANCIAL VERSION DIM].[Financial Version].[Financial Category].&[ACTL])'

select

{[TIME DIM].[Time Main].[Year].&[2005].members}

*{

descendants([GROUP EVENT DIM].[Group Event].[Hotel].&[12]

,[GROUP EVENT DIM].[Group Event].[Group Event])}

 

  1. 使用Exists函数

尽量的使用Exists函数替代筛选成员属性

 

  1. 避免Lookup

避免使用lookup函数,尝试通过在同一Cube中进行修改来提供度量值。

 

  1. 对于单一成员使用Minus而不是Filter

当从集合中筛选单一成员时使用Minus

避免:

filter({set},.Currentmember <> "UNKN")

推荐:

( {set} minus {&[UNKN] member})

 

  1. 杜绝使用值为常量的计算成员

尽管在简单的例子中可能没有差别,但是和其他计算混合时,就会产生非常复杂的执行计划。

避免:

with

member [a].[NiceName] as '[a].[123]'

member [Time].[YearBefore] as 'parallelperiod( [Time].[year], 1, [Time].[2006].[jan] )'

select { [a].[NiceName] } on 0,

{ [Time].[2006].[jan], [Time].[YearBefore] } on 1

from [MyCube]

推荐:

 select { [a].[123] } on 0,

{ [Time].[2006].[jan], [Time].[2005].[jan] } on 1

from [MyCube]

 

  1. 如何检查cell是否为空?

通常,检查空cell是为了避免除0错误或是检查是否丢值(NON EMPTY分析)

  1. 检查非空,避免除0

IIF(b=0,NULL,a/b)

在算术操作中空cell都是0

  1. 检查空cell(NON EMPTY分析)

Filter([dimension].[hierarchy].member.members, isEmpty(dim.member))

 

这里使用了IsEmpty函数。细心的读者可能发现,如果cell值为空就会被当做0处理,但是如果b有值,而且值为0,这就是非空了!因此,在用户希望区分空值或者遗漏值的时候,就要使用IsEmpty,但是对于除0就不适用了。

 

注意:不要使用IS操作符(ie: IIF(b IS NULL, NULL, a/b)) 检测cell值是否为空。IS是检查成员b是否存在。

 

  1. 杂项

 

  1. 避免赋给cell类似于0, Null, N/A, - 这样的值,cell还将是空值,另外使用Format_String做自定义UI格式。
  2. 避免冗余的Sum/Aggregate计算,默认的cell 会做值的聚合
  3. 试着避免使用IIF。如果不得不用IIF
  4. see if its possible to write it in such a way that one of the branches (then/else) is written “null”.
  5. 尽量使用字面意义上的hierarchy member(),(e.g. Measures.Sales 替代 Dimensions(0).Sales, Product.[All] 替代 Product.Members.Item(0)).
  6. 如果希望获取当前cell的值,考虑使用显式的度量的名称,而不是Measures.CurrentMember
  7. 在编写类似于"exp1 * exp2"的计算时,避免在左值使用在Cube中有更大空间的值。比如,用Sales * ExchangeRate替代 ExchangeRate * Sales, and Sales * 1.15” 替代 “1.15 * Sales”.
  8. 考虑在DSV或者SQL数据源中替换掉类似于Measure1 + Measure2 这样的计算
  9. 避免使用类似于Sum(Customer.City.Members,Customer.Population.MemberValue)这样的表达式,考虑在City表上单独定一个度量值组,带有Population列的Sum度量值
posted on 2009-07-09 15:24  Jonnas  阅读(1669)  评论(0编辑  收藏  举报