IT技术网www.itjs.cn

当前位置:首页 > 数据库 > SQl Server > Project REAL分析服务技术探讨(1)

Project REAL分析服务技术探讨(1)

发布时间:2015-11-29 00:00 来源:未知

内容目录

关于Project Real 

和分析服务交互的三种方法

有三种方法来和分析服务交互:SQL Server管理环境(Management Studio),项目模式下的商业智能开发环境(Business Intelligence Development Studio)和连接模式下的商业智能开发环境。我们将逐一的实施检验它们,并将向你描述假如你不能适当的结合这些工具方法,将带来的无穷麻烦。

SQL Server 管理环境(Management Studio)

在你启动SQL Server 管理环境之后,系统会直接连接分析服务的服务器,并能马上完成请求连接的操作。

例如:假如你处理一个Cube或者维度,系统内部将使用受控的API,也被称为分析管理对象(Analysis Management Objects ,AMO),通过这些对象来查找信息以及请求管理功能,例如:对象处理。一些操作是通过AMO来实现的,另外一些是采用XMLA脚本来实现,但是无论是那种方法,都是依靠运行的分析服务服务器来完成的。由于分析服务支持并发访问,系统保留了结构上锁的特性,用来避免在多个操作并发的时候产生的冲突,例如:当某个维度正在被一个操作处理时,这个结构能够阻止试图删除这个维度的操作。

SQL Server 管理环境(Management Studio)是作为一个管理应用程序而被设计的。它并不是一个开发环境。它允许你用它来浏览分析服务(Analysis Services)服务器和执行各种相关的操作活动,例如执行备份和恢复;同步服务器;配置服务器等。当SQL Server管理环境完成基本对象管理时,例如更改少量的属性或者删除对象,它就需要依靠其它的程序来设计和配置分析服务对象。

BI Development Studio 项目模式 (默认模式)

想要设计和实现 Analysis Services 数据库的开发人员和数据库管理员可以利用BI Development Studio 与 Analysis Services 相合作。BI Development Studio 是运用 Microsoft Visual Studio® shell 构建而成的。利用BI Development Studio 完成操作与利用其他SQL Server 工具完成操作非常类似(例如创建一个集成服务包或者产生一个服务报告)。 Visual Studio shell 的一个原则就是开发是一个反复编辑,构建,配置的迭代过程。

对于Analysis Services来说,这就意味着你一旦开始了一个Analysis Services项目,你便与Analysis Services服务器分离开来。起初,你通过如下任意方式构建项目:1)从相关资源中创建维度,cube和其他对象,为Analysis Services server创建项目。2)从服务器中获取一个已有的Analysis Services数据库,并在库中创建项目。一旦项目被创建,它便与Analysis Services服务器分离开来(并且和其存在的数据库也分离开来)。你可以在飞机中或是家中利用便携式电脑脱机的获取项目。仅当你重新与Analysis Services服务器连接。

当开发项目时,BI Development Studio将检查对象在项目中和Analysis Services服务器中的不同。这些不同点用于同步项目与Analysis Services服务器。这就意味着创建了在脱机状态下创建的新对象,编辑了在脱机状态下改变的属性,删除了在项目中没有但是在Analysis Services服务器中存在的对象。

数据库设计

项目REAL Data Warehouse在一系列的多维Analysis Services数据库中执行,这些多维数据库称为:

◆REAL_Warehouse_V代表数据的data-masked版本)是几千兆数据库版本

使用数据源视图扩展元数据(metadata)

通过使用数据源视图很直接也很容易扩展元数据。在Project REAL中,我们以下几种方法使用扩展的元数据。

◆我们使用扩展的元数据来创建在离散化分组中用于数据转换的计算列。例如,Item维度有一个为称为Publish Year的属性。不管怎么样,年份都具有一些分析的意义。如何区分一个出版于1934年的书和一本出版于1992年的书?一个用于分析更好的属性应该是自出版以来已经有多少年了。因此,我们在Item表中创建了如下图所示的计算列(使用数据源视图)。

ISNULL(DATEDIFF(yyyy,Publish_Year,GETDATE()),0)

这个使用标准SQL函数的语句,将出版的年份转换到一个变量,变量的值是从出版年到现在已经有多少年了。

分析服务支持自动离散变量(例如自从出版以来的年份)。使用数据挖掘运算规则,分析服务能将值存储到统计出来的有意义的分组中。在这个例子中,我们最后得到以下十个分组

-3 到1 年 (因为Item表中包含在未来3年后才能出版的书籍,因此-3是一个有效的值)

结论

总的来说,数据源视图在分析服务中有两个重要的角色。

首先,它们是在分析服务使用对象和数据源之间一个抽象的层。这允许你创建类似命名查询和计算列这样的对象,这些对象也能在数据源中直接创建(例如,关系型视图)。这很重要,因为分析服务的管理员可能没有必要的权限去改变源系统上的元数据。例如,源系统可能是一个保留了主要的私人信息的组织级的SAP系统。作为组织的资源,管理分析服务服务器的DBA可能没有权限在这个源系统中实现添加、移除或者改变视图这些操作。但假如把这些改变放到数据源视图中,DBA就能从一个抽象的层获得好处,而不必再去改变源系统上任何信息。

数据源视图允许你在那些不在物理数据库上或者不可能位于不同的数据库上的表和视图之间创建关联。例如,你不能在两个存储在不同数据库上的表创建外部关键字约束。这个关联对于那些从3NF或者OLTP数据库构建的维度是很重要的。

不要让数据源视图失去自控能力。毕竟它们只是一个工具,而不是一个万能药。假如你开发了一个很好的多维度设计,你可能会发现它们不仅仅是很有趣的工具。

维度(dimensions)

在Project REAL中,我们有大量的、复杂的维度。这也是带我们到这个特殊应用程序的内容之一。这有大量的分析是基于厂商所扮演的角色。这里有许多半可加性的度量,例如库存数量以及其它类型的库存数据。这种多维度设计对于那些已经开发或者正在维护零售数据库的人员是非常熟悉的。

维度键

维度包含的内容主要是用来过虑或者考虑真实表的各种度量。Cube中的维度都会映射到一个关系型的维度表。

逻辑模式有两种类型的键:代理键(Surrogate keys)或者业务键。代理键被用来表示表之间的内部关系。业务键(Business keys,有时也称为natural keys)是为了从业务本身中标识一个实体。因此,例如,尽管厂商被代理键(使用一个标识的属性,例如1-n)指定的时候,但在外部世界,它们自然键(natural keys)是一个厂商编号-例如,厂商#7233703。对于真实的表,ETL过程都会将业务键映射到代理键,因此,当记录被暴露到分析服务的时候,事务就已经发生。

在我们的案例中,代理键被用来跟踪第二种类型缓慢变化维度。你将发现,所有的维度键属性都使用了代理键列。我们在维度键属性上不使用自然业务键,因为多个第二种变化类型记录可能会有相同的业务键。尽管各种类型和缓慢变化维度的使用已经超出了本文的范围,但数据模型本身还是在推断的成员中使用了第一种类型和第二种类型缓慢变化维度用来插入,可以参见Project REAL: Business Intelligence ETL Design Practices 白皮书。我们也推荐在http://search.barnesandnoble.com/ booksearch/isbnInquiry.asp isbn=0471200247网站上的Ralph Kimball的书籍《The Data Warehouse Toolkit, Wiley, 2nd edition》

层次(hierarchies)

尽管维度在报表中给出了度量的上下文和意思,但终端用户实际使用的分析对象是层次(hierarchies)。SQL Server 2005分析服务中,提供了两种类型的层次:属性层次(attribute hierarchies)和用户定义层次(user-defined hierarchies)。

在层次中是各个级别的集合。层次中每个Drilldown就是一个级别。例如Time层次中包含Year、Quarter、Month、Week和Day几个级别。在Book层次中(Project REAL中还用Item来表示)有Type、Subject、Category、SubCategory和Item级别。

报告层次(Reporting hierarchies)

第一个用户定义层次类型是报告层次。这个层次仅仅是用来报告的。潜在的数据并不支持各个级别上的关联信息。例如,我们有一个报告层次被设置成ALL->Author->Item。这样报告的目的仅仅是因为一个Item能够决定一本书,而其它的却不行。在层次中将作者放到Item前面,将产生一个多对多的关系。

自然层次(Natural hierarchies)

另外一种层次类型是自然层次,也被称为强层次(strong hierarchy)。在自然层次中,层次中的数据和其它的层次都有一个多对一的关系。日上 滚到周;周上滚到月;月上滚到季;季上滚到年。这将允许系统能够预先计算一个上滚动作或者是集合,例如为获得根据City的Store Sale的子集,然后根据City计算State;根据State计算Region;根据Region计算国家(这些求和都是基于层次的)。你能够重新打破或者再细分这些自然层次,因为每个成员都有且只有一个父亲。

自然用户定义层次不是SQL Server 2005新带的属性。它们在分析服务的早先版本中就存在。新的在于一种报高层次,它们是使用属性层次来构建的。

属性层次(Attribute hierarchies)

属性层次是SQL Server 2005中一个新的层次类型。它是基于维度表中的属性或者列。本质上任何数据库中的列都能成为维度的属性。当一个属性被定义到一个维度,一个属性层次就生成了。这意味着,假如时间维度表有一个Holiaday列,它只使用0或者1来表示某天是否是假期,然后你能够基于这个列创建一个Holiday属性层次。属性层次是平直的(Flat)。当一个层次只有两个级别的时候,我们称它为平直的。这两个级别是:所有的级别(把属性的所有值都加起来得到一个总的值);另外一个就是它自己。由于Holiday作为一个在用户定义层次中的独立的层次存在并使用,因此终端用户能够通过Holiday实现销售情况的分析。SQL Server 2000分析服务中有一个类似的概念,叫做虚拟维度(virtual dimension)。尽管使用虚拟维度,你能够基于每个成员属性创建一个维度,但虚拟维度在范围和伸缩性上都有很大的局限性。

基于层次系统(hierarchie-based systems)和基于属性系统(attribute-based systems)的对比

这是两个SQL Server 发布版本重要的、基础性的区别。

SQL Server 2000分析服务是一个基于层次的系统。内部结构都导向层次或者级别。这包括了,像集合,是级别的一个捆绑,每个都针对一个维度;像虚拟维度,将成员属性提升为维度。一个维度智能有一个层次。多层次是一个命名惯例。两个时间层次,例如Time.Calendar 和Time.Fiscal,看上去,它们都和Time相关,但在内部,这是两个不同的维度,只是恰好它们的名字上都有Time。一个名称为Product的维度也有可能是名称为Product的层次。在维度和层次之间没有严格的差别。

SQL Server 2005 分析服务是一个基于属性的系统。属性是构建对象的基础。集合是捆绑属性的求和。默认情况下,属性层次会自动的为属性创建。一个维度能有多个层次。在一个时间维度中,Time.Calendar和Time.Fiscal是两个层次(Calendar和Fiscal)。用户定义层次(例如Calendar和Fiscal)纯粹的用来导航实体。它们存在不仅仅是为了辅助属性的组织。你马上将会看到,这样的概念将在整个文章中被反复的出现。

维度中使用了如此多的逻辑结构。现在,让我们来看看维度的一些物理特性。在这里,我们首先讨论它们使用的内存。

分析服务2005中的维度缓存

SQL Server 2000和SQL Server 2005各自的分析服务在处理维度成员时,有很大的不同。在SQL Server 2000中,在启动的时候,所有数据库中的所有维度成员都需要被加载到服务器的地址空间上。这种情况下,内存就不能为其它程序提供很好的服务,数据缓存也将超出维度的内存。这样局限性就很大。这意味着,在一个32位的系统上(只有3GB的虚拟地址空间,但分析服务无法意识到这点),你能够具有的所有维度成员最大的数目也就几百万而已。假如你限制你成员属性的数量,并且保持这些属性很短的名称,这样你才可能达到3到4百万个成员。只要超出这个限制,你就不得不使用64位的服务器,以得到更大的虚拟地址空间。这是因为就Item维度就大概包含了七百万个成员。Customer维度大约有5百万条记录。这已经大大超出SQL Server 2000分析服务在32位系统上的承受力。

在SQL Server 2005种,分析服务使用一个动态的维度缓存,并不是将所有的成员都静态的映射到内存中。系统会在成员被要求的时候才把它们加载到内存中。在其它维度成员被请求的时候,会释放先前的成员。我们成功的在32位硬件和64位硬件上构建了整个Project REAL系统(事实上,存在这个系统的很多个版本)。并且对于这种大型系统,在32位系统上也能良好的运转。

我们也发现了那些不能构建到32位系统上的维度。但这里的上限跟SQL Server 2000的上限比,那就要大的多了。这主要取决于用来处理维度键属性的属性层次的hash表。当你使用太多的属性(或者假如属性的规模太大),然后最终超出了可用的内存,这个维度就不能被处理了。

对于维度来说,恰好落到不能被构建的界限里面是因为它们太大以至于不能加载到内存上,下面有两种方法减少需要的内存,来处理它们。

首先,确保所有的属性都确实需要被用来进行分析。假如不是必须的,从维度中去除它们。这能使得Hash表要求的空间更小。

第二,使用级联的属性关系,这样能够最少化属性的数量,因为它们都直接依赖于键。每个属性必须直接地或者间接地关联到一个维度地键。当你第一次创建维度地时候,你将注意到,所有属性都直接地关联到一个键。这也是键属性的特征之一,所有属性都能关联到它。然而,作为为维度定义的自然用户定义层次,一些属性会生成额外的关联。这样,它们既直接关联到键,也通过自然层次,间接的关联到键。例如,假如你清楚Time维度中的Day,你也将知道Year(Year直接被Day暗示)。同时,Day也暗示了Week、也暗示了Month、也暗示Quarter、也暗示了年。因而,在定义自然的用户定义层次后,你就能把Week、Month、Quarter和Year从Day的直接关联中去掉。假如间接的关联存在,就删除直接的关联。

依赖的属性能被移除,因此它们不再直接依赖于键,但它们通过在自然层次中通过属性关联能够间接的关联到键。并且,它们也能从维度的键属性中移除。这是一个很好的例子,详细参见图2。

Project REAL分析服务技术探讨(1) 

图2:一个时间维度的良好设计

对比如何将属性关联定义到calendar属性上和如何将属性关联定义到fiscal属性上。绝大部分calendar属性不是直接关联的键属性(Day)的;仅仅只有Week。相反,绝大部分calendar属性能够向上级联到calendar自然层次。Fiscal属性关系也是这样一种情况,只是属性都是直接关联到键属性上的。

这个方法认为calendar属性应该是首选的方法。假如你定义了自然的用户定义层次,或者其它具有级联效果的属性关系,你就必须将直接的关联移除掉。这里有两个原因。首先是这样消耗更少的内存。第二是当集合设计向导(Aggregation Design Wizard)运行的时候,多余的直接关联将导致更慢的集合设计。

属性关联

在图2种,标记了两个属性之间定义的关联。标记了日和周、周和月、月和季以及季和年之间的关联。当你这么定义的时候,这代表了什么呢?有趣的是,这意味着那里有一种多对一的层次关系。只要给定一个周,你就知道有也只有一个月包含这个周;给定一个月,你知道有也只有一个季包含这个月;同样,给定一个季,你就知道有也只有一个年包含这个月。基于此,系统能优化它的计算,因此它能够向上滚动,体现出这种层次关系。

最佳实践:多花点时间用于维度的设计,在维度种捕获这种属性关系

重点:假如你想设计有效的集合;假如你想通过计算引擎,实现有效的计算;或者你想验证MDX时间函数的结果,你就必须定义属性之间的关联。

在SQL Server 2000分析服务中这种基于层次(仅仅支持自然层次)的性质,集合就是根据层次来设计的。在SQL Server 2005分析服务中,集合可以和属性绑定。用户定义的层次是不能使用的。存储设计向导(Storage Design Wizard)使用属性关联来决定什么时候绑定属性向上滚动,这是很有用的(因而,需要为那些属性设计集合)。没有关联,任何一个属性都和其它的属性一样重要,因此,存储向导会简单的忽略属性,并为维度使用All级别。因此,假如你想要设计一个有效的集合,你必须定义属性关联。没有关联,系统仍然会返回适当的数目,但必须在运行的时候才能得到计算的值。这样,集合就没有用了。

当计算复杂的MDX表达式的时候,规则引擎也会用到属性关联。没有属性关联,例如non-empty交叉连接这样的操作不能被优化或者有效的处理。因此,假如你想从规则引擎有效的执行运行时计算,你也必须定义属性关联。

最后,在时间维度中,属性关联也很重要。许多和时间相关的MDX函数只有当属性关联和属性类型被设置正确的时候,才能返回有效的结果。一般地,你能依靠商业时间智能向导(BI Time Intelligence Wizard)来设置适当的结构和关联。无论如何,在你手工的定义时间维度以及使用MDX时间函数的时候,假如你想获得有效的结果,你必须在你的时间维度中定义属性关联。

有两种类型的属性关联。第一种关联类型,也就是到目前为止我们一直在讨论的,当需要设计集合的时候,系统用来表达在哪里向上滚动的关联。假如读者对SQL Server 2000分析服务比较熟悉,他将会注意到,同时还存在另外一种关联类型。这就是类型的成员属性。

例如,在Project REAL的逻辑模式中,我们有一些属性,例如地方经理的名字以及他(她)的电话号码。这些属性被我们分别规格化到Store维度表中。这些属性由于不同的显示目的或者不同的分析要求,因此都是各不相同的,例如地方、地区和仓库等。一些分析是基于地区的,而不是基于经理的电话号码的。当经理名字和电话号码不必用于分析,我们就可以将它们关联到地区。假如你知道经理的名字或者电话号码,然后就将自动的获得经理所在的地区。因而,在这两个属性之间表达了一种关联。然而这种关联对于分析是没有用处的,但对于终端客户工具是有帮助的。因此将这种成员属性表达为关联,必须在适当的位置标识这种关联,以至于当终端用户右键单击成员的时候,客户端工具能够显示成员属性的列表。

总的来讲,为了确保你设计和实现一个能正常工作的系统,就需要指定属性关联。否则,将会带来隐患。

键的唯一性

在维度中,SQL Serveer 2005需要将一个属性标识为键属性。这个键必须是唯一的。当系统处理维度的时候,它会要求你确保这种唯一性。这对于熟悉SQL Server 2000分析服务的管理员而言,是一个巨大的挑战。

SQL Sever 2000分析服务基于层次的特性允许DBA以多种方法表示键的唯一性。整个维度中的成员键都是成唯一的。例如,在一个维度的所有成员中,只有一个成员的键值为#42。或者,唯一性也能设置到一个级别。例如,Subject级别可能带有一个键值为#42的成员,但Item级别可能也有一个键值为#42的成员。或者唯一性也能够被关闭。在这种情况下,可能会有键值为#42的多个成员。仅有的约束是键值相同的两个成员不会是相同的父亲。系统内部实际发生的是,对于一个仅有一个层次的维度,即使你没有指定唯一的键,它也会创建一个唯一的键。

在SQL Server 2005分析服务中,一个维度可以包含多个层次。或者它可以不包含用户定义层次而只包含属性层次。这对于键的唯一性意味着什么呢?由于一个属性在没有其它结构化层次情况下,必须能够标识自己,例如一个平直的属性层次,键值#42意味着什么?最终,它表示这个键值是一个真实的键值。更确切的说,它必须唯一的表示一个属性。

除了键属性的唯一性,系统也考虑了其它属性的唯一性。当然这不是强制性的。假如我们不设置维度,确保属性键的唯一性,会带来预想不到的结果。

最佳实践(必须的):你必须总是确保属性键的唯一性。

首先,我们将想你解释如何为一个属性指定一个唯一的键,然后我们将想你阐述假如你指定错误,将发生什么事情?

假定你正在为你的项目(跟我们的Project REAL类似)创建一个标准的时间维度。作为维度中的一个属性,考虑以下Month列。它包含了从1到12的整数。一般你会设置如下:1 = 一月;

考虑一下对话框中行的数目也是一件有趣的事情。在我们用Year创建链接键之前,Month属性层次返回了13条记录。这就是当我们根据一个未知成员的月键,使用SELECT DISTINCT,你期望得到的结果。当我们添加了Year链接键后,新的处理会返回219条记录,因为SELECT DISTINCT语句中包括了年。

以下是几个注释。首先,假如你使用Project REAL提供的一个相同的数据库,执行这个练习,在维度处理过程中,不会产生任何错误(警告或致命的错误)。你必须扫描你的维度,并留意成员没有出现在预定位置的情况。

记录键的唯一性被用于约束相关的属性。假如你没有指定相关的属性,那所有的属性都被关联到键。由于键必须是唯一的,那所有的都没有问题。然而,当你开始指定相关的属性,你大概能说出关于属性的一些事情。你会说,这个键是唯一的。注意在过去不久的文章里的例子中,当我们发现键不唯一而带来问题的时候,就是发现相关的属性了。

假如我们不能再生成唯一键,我们智能选择移去属性相关性。我们这么做之后,属性就智能直接的关联到键属性,键属性要求是唯一的。没有相关的属性使得产生一个高质量的集合设计成为一件不可能的事情。这也是分析服务中的对于“键”你最后应该注意的地方。最后再强调一样,一定要确保在整个维度中,所有你设计处理的键都应该是唯一的。

最佳实践:总是扫描你的维度,确保它们包含你预期的广泛的、甚至是分布的成员。

假如你看到一个专注于分布式的,然后发生了一些不可能的事情。要么就是唯一键没有标识出潜在的属性或者层次的顺序不准确。例如,你疏忽的指定了Year、Month、Quarter而不是Year、Quarter、Month。上述两种情况都会导致不正常的层次,但在处理过程中,不会有任何提示。

假如你打算定义一个属性关系,它们必须在数据上基于有效的模式。属性关联对于设计和实现一个高性能的系统是非常重要的。假如一个键结果导航系统执行一个错误的上滚操作会发生什么呢?例如,假如你在一个正常层次中颠倒了两个级别,会发生什么呢?

假定你正在定义一个Store正常层次的顺序是(All、Region、District、City、Store),实际上定义的却是(All、District、Region、City、Store)。正常的顺序是由属性关联来构建的。在这种情况下,这种单方面的被用于构建一个属性关联就不在被数据所支持。一种情况可能是一个Region能上滚到许多个District。然而这种计算是错误的。在运行时,数据被计算了两次,并且在层次上也是错误的。系统不能正常运行并返回错误的结果。所以,在定义属性关联的时候尤需注意,因此即使定义错误也不会返回任何错误。

最佳实践:假如你告诉系统属性是关联的,则它们必须是关联的。

数据必须支持关联。另外,键的唯一性必须允许这些关联能够被执行。

这就带来一个有趣的问题。假如你只是没有定义相关的属性,将发生什么?令人惊讶的是,一个有效层次返回了一个正确地结果,如图6所示。

Project REAL分析服务技术探讨(1) 

图6:没有定义属性关联的Time

图6所示的层次看上去是有效的。当你查询一个系统,数目都是正确的。问题在于,没有相关的属性,系统无法意识到属性之间重要的关系。这种关系标识一个上滚是能够在层次上预先计算好的(SQL Server 2000分析服务使用集合达到这个目的)。相反,系统不会在查询计算的时候使用它的运行时来完成上滚。由于没有设计集合,因此你没有告诉系统层次里面的属性是相关的。所以,你得到一个清晰的层次并很好的列举了层次,但是你不能使用预先计算的集合用来计算子集,因此性能收到了影响。

将虚拟维度转换成属性层次

不幸的是,在我们的Project REAL中,我们不能包含我们在转换到SQL Server 2005之前在SQL Server 2000分析服务中设计的文档。相比于最终的设计,原先的设计要更加简单一些。现在差不多有一打的维度被去掉了。取而代之的是属性层次,绝大部分都是在Item维度中。例如,原先的系统携带了五个虚拟的维度,这些维度是在Item维度中,基于厂商关联建立起来的。 因此,在原先的设计中,都是用维度来针对Source Vendor,Return Vendor、Purchase Vendor等。那么在使用SQL Server 2005 的REAL的最终设计中,它们分别被Item. Source Vendor, Item.Return Vendor等属性层次所取代。在原先的设计中,还包含了一个Department正规维度(这个维度构建于一个Item维度的视图)。在最终的设计方案中,也被Item.Department 属性层次所取代。

最佳实践:将SQL Server 2000分析服务中的虚拟维度转换成属性层次

假如一个虚拟维度超过一个级别,那么能使用相关的属性作为级别,把它转换成一个用户定义层次。迁移向导(Migration Wizard)将帮你自动的完成这个工作。然而,当你手动的迁移或者在SQL Server 2005中重新设计的时候,你都应该意识到这些自动的转换。假如在虚拟维度总,仅有一个简单的级别,那么可以直接从数据模型中(和应用程序代码中)直接删除这个虚拟维度,直接使用属性关联即可。当你在考虑你的2005设计的时候,需要重新考虑每一个维度,并询问自己是否能将这个实体作为其它维度的属性?假如确实是这样,就可以用属性层次来代替。这能够降低系统的复杂性,对于终端用户也具有更多的意义。这些属性层次都揭露了原来的维度类型,并且这样做能增加一些对潜在的多维度设计的理解。

例如,原来Project REAL的设计中包含一个被称为Department的虚拟维度。它标识书籍能在那些仓库部门(例如硬皮或者软皮书籍)购买到。Department虚拟维度是从Item维度的一个成员属性上获得的,我们将它转化为Item维度中的一个属性层次。因而,终端客户能够清晰的看到相关联的Item,而不是Stores或者其它的维度。

可能的命名冲突

在同用户定义层次一起工作的时候,你可能会遇到命名上的冲突。这是因为用户定义的层次和属性层次一样共享了一样的命名空间。在SQL Server 2000分析服务中,有两种类型的名称:

维度/层次名称和级别(Level)名称。在分析服务2005中,有三种类型的名称空间:维度、用户定义层次和属性层次。因为用户定义层次和属性层次有相同的命名空间,因此就产生了潜在的命名冲突。

例如,你已经有一个名称为Buyer的维度。由于很多前端工具只显示层次的名称,所以你可能会创建其它名称为Buyer的层次。在分析服务2000中,你可以这么做。现在的挑战在于,假如你创建了一个名称为Buyer的层次,你将不能再创建一个名称为Buyer的属性层次。在Project REAL中,我们把属性层次重新命名为Buyer Name。如图7所示,所有相关的对象都必须唯一的被命名。

Project REAL分析服务技术探讨(1) 

图7:在属性层次和用户自定义层次之间的命名冲突

你不能在将一个属性层次命名为Return Vendor,也不能将一个用户定义层次命名为Return Vendor。因而在我们的设计中,我们扩展了在SQL Server 2000分析服务中使用的典型命名转换。在复杂的情形下,在名称经常被重用到的地方,我们用“By ”来命名用户定义层次(name代表了在用户定义层次中整备分析的属性)。对于这个对则也有一个例外。存在一些知名的关系,我们不必再做出澄清。例如Time.Calendar和$12.50。“By ”这个规则不是很适用。Time.By Calendar和Time.By Fiscal 看上去很不正常。但是对于那些用户定义层次和属性层次有相同名称的情况而言,命名转换是一个很有用的窍门。

将关系表中的列提升为多维度设计中的属性

每当我们检查Project REAL多维度设计的时候,我们经常问我们自己,是否需要在数据源视图的维度表中包含一个特殊的关系列作为一个属性视图。我们把这个过程称为提升(Promoting)列。

Project REAL分析服务技术探讨(1) 

图8:提升数据源中的一个列作为一个维度的属性

例如,在数据源视图的维度表中,一个Item维度有超过144个可用的列。为所有的这些列创建属性并不能很有效的利用资源,因为一部分列在分析中从来没有被用到。最后,我们决定使用其中的44个列作为维度中的属性。

一个有趣的设计问题是是否需要将维度表中的所有列都应改添加(或者提升)到一个属性层次中。默认情况下,维度向导(Dimension Wizard)能够完成这项工作。它会将所有的列移动到一个属性层次。你不得不手动地把某些列从属性层次中去掉或者防止被提升(Promoting)。无论是不提升一个列使其成为属性还是依赖于关系型数据源的复杂性和丰富性,都是一个很好的选择。

我们体传了一些指导方针,帮助你确定什么时候将一个列提升为属性。你会发现这些信息非常有用。

◆首先,确定你是否需要对这个列进行分析。属性层次是一个最基本的方法,帮助终端用户完成分析。它们使用将它们选择的属性层次作为对象使用,点击或者拖拉,区分或者转动。假如一个列不是属性,它们将不能被操作或者分析。

统一空间模型(Unified Dimensional Model ,UDM)的真正力量在于它采取了一个丰富的属性层次集,能够帮助用户完成数据分析。这种分析可以使用预定义的对象,例如用户定义层次或者那些可以完成特殊操作的对象。属性层次对于特殊分析是很有用的。例如,你可能想分析比较某个地区精装书和简装书销售情况。用户定义层次Store.ByGeography允许你一直向下钻,知道你想要的一个级别,也就是地方或者地区。另以方面,你能够将Item.Department属性层次拖到网格上,网格中包含了关于精装书和和简装书的数量情况。假如你没有将Department提升到属性,你将不能完成这样的操作。

假如你希望将来在一个列上面能执行分析,那么你应该将它提升为属性。例如,Item维度表包含了一个被称为Original EAN的列。这个分配给书本的第一个EAN值。(这个数目将来可能会变化)。我们决定,终端用户不会做基于它的分析,因此我们没有显示它。由于当前的EAN数目还没有达到要求的地步,因此大家要马上将它提升为维度的属性。但是,我们可能犯了一个错误。假如将来有用户想使用这个列用于分析的机会,我们将把它提升为属性。

在一个大表中,你不能提升任何列。当一个表中包含很多潜在的可提升列,需要决定提升哪一个是一项挑战性的工作。例如,在Project REAL的Item表中有超过144个列,它们都可以被提升为属性。让用户自己来跟踪这些信息显然是不合情理的。

◆假如一个属性只有在层次上下文中才有一点概念上的益处(换句话说,它基本上没有分析的潜力),可以将它提升为一个属性层次(这样你能够把它添加到一个用户定义层次上),但需要将它设置成隐藏。这不会干扰终端用户的视线。

和tinyint键不匹配的数据类型

在关系型设计中一个很出名的经验是你应该总是应该使用那些能够满足你正在使用对象范围要求的最小数据类型。假如你知道这点(出于商业原因),一个数值总是不会超出一个极限,就不要使用大的数据类型。这样做只会浪费存储空间。尽管,这总是一个很好的建议,但要提防在SQL Server 2005中,当我们处理tinyint的时候,可能会带来数据类型的不匹配。Tinyint键值作为byte类型(从1到255)保存。当数据源视图被创建后,假如tinyint键是一个标识列(可能是一个代理列),然后系统将把它转换为integer。因此维度的键是一个integer。但是,在你实际的表格中,智能保存tinyint的值,这可能会导致类型不匹配。

例如,在原先SQL Server 2000格式的Project REAL设计中,Department 维度是一个完整的维度表。Department 键是一个tinyint值(从1到13),包含了书本的类型,例如精装本或者软皮本。Department 键有一个Indentity属性,因此下一个值应该是14,然后是15等等。因为,往往是选择能够满足需求的最小数据类型,因此选择了tinyint。在这种情况下,原先的设计人员认为不会超过255个Department。自然地,实际表中有一个外部关键字,也是tinyint。当我们将设计前一到SQL Server 2005分析服务后,将导致数据类型的不匹配。

在这种情形下工作的时候,需要在数据源视图的维度表上创建一个计算列,需要显式的将键列转换成tinyint类型。然后,在维度的关键属性层次中舍弃原来的列而使用这个新列。尽管你也可以将实际表中的tinyint类型转成integer类型,但这会造成空间上的浪费。

尽管你会认为这可能是一个Bug(我们也这么认为过),事实上,这是由于早期使用Microsoft XML Core Services (MSXML)来进行开发造成到。在MSXML中,主张一种隐式的数据转换,能够将一个未知的数据类型转换成它们想要的数据类型(跟SQL Server RDBMS式不一样的)。在这里,tinyint是从SQL Server 早期遗留下来的数据类型,MSXML事实上直接将它转换成了integer类型。假如解决这个问题,有太多现存的MSXML代码需要修改,因此,我们不得不保留这种情况。

未知成员

决定一个系统如何处理未知值总是一个有趣的设计决定。在SQL Server 2000中,这个是很简单的,你只是需要创建一个你自己的应用程序级的未知成员。这包括在你的维度(Dimension)中添加一个未知成员以及在实际数据库表上添加一个ISNULL或者其它的关系型技术。在SQL Server 2005中,提供了一种新的技术,允许系统生成一个它自己的未知成员,并将它自动的赋给未知值。

在Project REAL中,我们采用这两种方案。在绝大部分NULL值上,我们创建了应用程序级的未知成员(我们称它为”missing”)。这种方案,在视图中的绝大部分工作都可以完成,也包括通过代理键值为0,来返回已丢失的信息。显然,当NULL值不使用0表示,而使用一些看上去就是异常的数据,这种方法会让系统看上去更完美。我们可以使用合理的“丢失”数据(我们预期的一些信息)来表示一些异常的无效数据(也就是无效的数据)。使用系统生成未知成员的问题是你不会察觉到逻辑上不合理的数据和无效、异常数据之间的区别。

最佳实践:在可能的地方,创建你自己的未知成员。使用系统生成的未知成员。

下面的代码是关于一个如何在关系型视图中如里未知成员的例子。

CREATE VIEW [dbo].[vTbl_Dim_Store] AS

图10表示我们如何在Store Sales部分改变错误配置。

Project REAL分析服务技术探讨(1) 

图10:改变错误配置设置

图11表示当一个查询使用系统未知成员的时候,看上去是什么样的。

Project REAL分析服务技术探讨(1) 

图11:查询中的系统生成的未知成员

时间智能向导

过去当需要使用时间智能向导来创建新的时间维度时,我们遇到了一些挑战。SQL Server 2005 的分析服务(Analysis Services)是服务器端时间维度(dimension)。虽然,由于其容易使用的特性(只需点击几下就能得到时间维度),使用服务器端时间维度是很有诱惑力的,但我们并不推荐这种方法作为通用的实践方法。

最佳实践:可能创建单机时间维度表的地方

在处理复杂的时间情形时,拥有一张时间维度表会给你更好的伸缩性。

◆你能添加你自己的时间属性。例如,将某天指向周末还是普通的日子?某天时公司假日么?某天时季节内还是季节外?某天是在圣诞假期内么(对于很多零售商很重要)?

最佳实践:在时间维度向导中,为各个属性输入键列(非名称列),例如年、月、周。

选择键的好处在于,少后,你仅需要改变成员的名称。默认情况下,向导将把Order By属性设置到键上。因此,假如在这里输入一个键列,你稍后需要改变就仅仅是名称列。

在你运行完向导后,当我们开始涉及确定定义的时候,请牢记对成员键唯一性的要求。在这个时候,我们很容易去使用传统的键和名称。例如,你可能会把Q1,Q2,Q3,Q4作为名称或者键;或者你也可能像下面这种情况使用键值:用1代表1月,……,12代表12月。尽管数据库管理员都记得他们按照特定的顺序使用1…12作为月份的键值(否则4月有可能成为每年的第一个月),但我们并不能总是牢记这些顺序,因此值为Q2的季节或者值为4的月份并能够唯一的确定一个键。你经常需要回过头去,为成员键创建一个集合,并将年份添加到集合中以确定其唯一性。

不要忘记忘记给你创建的多层次对象创建属性关系。例如,在日和周之间、周和月之间、月和季之间以及季和年之间,创建一个属性关系。就像键的唯一性一样,假如你想要系统良好运行,这种关系也很重要。

一旦你确定了成员的名称,就需要确保时间层次上各属性键的唯一,需要建立一个属性关系用来支持你已经定义的多个层次,你也可以添加其它时间相关的属性,比如周末、假期和季节指示器等。

虽然时间看上去是一个简单的概念(毕竟,它只是一个时间戳而已),但你还需要在构建数据库表和分析服务对象上花费你大量的设计时间,以确保它们已被适当的设置。

度量组

Project REAL实现的关系型数据模型包括三张实际的表:Store Sales、Store Inventory、和Distribution Center Inventory。物理上,为处理大量的数据(例如,每周约1.4亿-2.0亿条存货记录),需要按周来分割这三张实体表。分割是很重要的,因为:

◆这能提供更好的性能。查询只会扫描覆盖某个时段的分割表。一般情况下,这些分割表越多,它们就越小,查询就会执行的更快。

分割表

系统在分割表中存储实体表。一个分割表和每个度量组具有相同的结构。它包含相同的列,数据类型也完全一样。然而,分割表也可以包含数据的一个子集。例如,它可能只包含一星期的有效数据。

在这个章节中,除非有特别的说明,否则都认为分割表保持Week的级别。数据库中有个名称为vTbl_Fact_Store_Sales_WE_2004_11_27的关系表。在Project REAL数据库的分割表看上去违反了SQL Server 2000的基本实践原则。在Project REAL中,割表没有数据切片设置。在SQL Server 2000中,分割表必须有数据切片设置,以至于运行时引擎能够确定访问哪一个分割表。这有点类似于给查询优化器指定一个提示。在SQL Server 2005中,这不在是必须的了。现在,处理分割表会自动的构建MOLAP存储中的一个柱状图结构。这个结构标识出在分割表中包含了那些维度的成员。因而,只要存储方法是MOLAP,数据切片是一个可选的(和不使用的)属性。然而,在ROLAP存储中,或者当proactive caching包含一个ROLAP访问阶段的时候,数据切片仍可以使用。在这两个环境中,真实的实际数据,都没有被移动过,因此,系统没有机会标识一个成员。在这种情况下,假如你希望系统能够良好的运转,为分割表设置数据切片还是有必要的。

因为由MOLAP结构动态地决定数据切片,因此在SQL Server 2005中,一种新类型地分割技术是有可能存在的。最好的描述这种技术是通过一个简单的例子。

假定你正在设计的系统由一个包含1000个产品的产品维度。在这其中,前5个产品占到了80%的销售,而剩下的995个产品只占到了20%。这种用来显示基于产品的查询结果的终端用户查询样式分析是一种通用且有效的分割模式。例如,绝大部分报表包含了通过产品分类的详情。基于这种分析,你可以创建六个分割表。前五个分割表都分别对应一个排在前五位的产品,第六个分割表包含了其它所有的产品。创建这个包含所有其它产品的分割表是很容易的。在查询绑定中,在SQL语句中添加Where子句就可以实现。如下面的代码所示:

对于前五位的产品,使用如下的代码:

SELECT * FROM

WHERE SK_Product_ID NOT IN (,

)

这种技术,在SQL Server 2000分析服务上,需要大量的管理费用。在SQL Server 2000中,必须给分割表中的每一个成员指定数据切片,即使哪里有几千个成员。为了实现这个例子,你不得不创建一个包含995个成员的分割表。当一个新的成员被添加到维度中的时候,更新这个列表也是管理上面对的一个严峻问题。在SQL Server 2005分析服务中,自动在分割表中构建数据切片的功能大大消除了管理上的成本。

另外面对的一个挑战是,当创建一个带有大量分割表的系统时,如何创建几百个分割表。在SQL Server 2000中,分割表可使用分析管理器(一个非常耗时,并会有潜在错误的过程)创建,而且每次只能创建一个。或者可以让开发人员编写一个应用程序来自动的创建。

在SQL Server 2005中,SQL Server 管理环境能够一次创建多个分割表,甚至是几百个分割表。一般情况下,当你创建一个分割表的时候,你需要使用那些定义在数据源视图中的表。毕竟,这也是数据源视图存在的原因。然而,这也不是必须的。在Store Sales度量组(请确认至少已经提供或者处理了一个分割表)上创建一个分割表,然后检查对话框,如图14所示:

Project REAL分析服务技术探讨(1) 

图14:创建一个新的分割表

注意,虽然对话框默认使用数据源视图,但你也能在数据源中查找和定位表。选择数据源然后单击Find,如图15所示:

Project REAL分析服务技术探讨(1) 

图15:查找一个用于分割的实际表

对话框列举了在数据源中能匹配包含在度量组“模板”表(或视图)的元数据(列和数据类型)的表。见图15。假如你选择了多个条目,系统会为每个选中的表创建分割表。

Project REAL分析服务技术探讨(1) 

图16:选择多个创建分割表的实际表

这回带来两个重要的侧面影响。首先,这意味着,不是所有的对象都来自于数据源视图。在Project REAL中,这意味着我们不必包含所有的23个基于周的分割表。我们只是包含了一个模板对象,用来创建度量组。第二,这也是节约时间的部分,你能够通过一个简单步骤就创建上百个分割表。仅仅只是选择多个对象,你就从一个操作中获得了大量的分割表。只是要求你在这之前已完成至少一个分割表的处理,以至于Find操作能够定位到相匹配的表。也就是这些,我们就可以通过一次点击,就能创建上百个分割表了。

存储方法(Storage method)

在我们的Project REAL工作阶段,所有的分割表都使用MOLAP存储。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

集合和集合设计(Aggregations and aggregation designs)

集合是将被系统计算的subtotal,用来提高检索速度。和集合本身一样,系统也保存了集合的设计。这是集合到底是什么的一种内在表示。设计描述了维度的结合以及应该被计算的subtotal的级别。集合和集合设计被保留在分割表中,这些分割表又都是包含在度量组中。

和SQL Server 2000分析服务将集合设计保存在分割表中不一样的是,在SQL Server 2005分析服务中,集合设计是位于第一位的。假如你查看由数据库提供的XMLA脚本,你会看到集合设计和度量组在相同的级别上。你可以同时有多个集合设计。在一个度量组中,每个分割表都会执行一个它所使用的集合设计。这有以下几种方法:没有集合设计(这也是不必为分割表创建集合的情况);一个针对所有分割表的集合;若干个不同的集合,每个都针对若干个分割表。绝大多数应用程序都使用第一或者第二中方法(要不就不使用集合设计,要么就是所有的分割表都是用一个集合设计)。在一些更复杂的设计中,你可以使用第三种方法(多个集合设计,各自应用于若干个分割表)。例如,你可以在一个当前年的分割表中使用大量的集合,对于最近三年的分割表使用适度的集合,对于三年的分割表,则不使用集合。在脚本上,很容易将一个分割表指向不同的集合设计,只要编辑XMLA脚本即可。

处理设置和错误配置

在度量组中保留分割表的同时,系统也会记录对这些分割表的处理设置和错误配置。对于Store Inventory和DC Inventory度量组,我们可以使用默认的错误配置。这种情况下,当系统检测到无效的外部键或者当它遇到NULL值或者当遇到其它不一致数据时,它会停止处理过程。这是因为默认情况下,系统认为所有的数据都是正确的。

对于Store Sales度量组,我们不得不使用不同的错误配置,假如你还记得在在度量组里面所讨论的,我们讨论了在Customer维度和Store Sales 实际表之间发现的无效数据。由于这是因为数据反馈之间正常的不一致性造成的,因此,我们必须修改默认的错误配置。

Proactive caching设置

考虑MOLAP结构的一种方法是当它被处理的时候,提供一个缓存或者一个关系型数据的图像。SQL Server 2005提供了一个新的功能,能够靠南固执MOLAP缓存什么时候被重新处理。提供了几个你能够改变的几个设置。例如,你可以设置硬编码的时间间隔(例如每隔15分钟)。或者,你能让系统等待数据直到数据被更新后,再处理它。这些设置都是保存在分割表中的。因而,也是保存在度量组中的。在当前的Project REAL系统中,我们使用了自动的MOLAP proactive cache设置。我们计划当我们进行性能测试的时候,再调整这种设置。

其它的Cube对象

除了维度的用法、度量组和分割表,在Cube中还包含了若干其它的对象。这个章节中将简要介绍计算(calculations)、关键性能指示器(KPIs)以及其它存储在Project REAL Cube中的对象。

计算(Calculations)

在当前的Project REAL系统上实现了多个为商业度量服务的计算。例如,计算平均销售数量和库存数量。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

关键性能指示器(Key Performance Indicators,KPIs)

在当前的Project REAL设计上还没有包含关键性能指示器(Key Performance Indicators,KPIs)。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

活动(Actions)

当前的Project REAL设计只包含了一个活动。这个活动被用来作为分析服务客户端和报表服务之间的一个桥梁。这个单元级别的活动,当被终端用户选择的时候,它调用一个报表服务的报表,并传递给报表适当的内容作为参数(例如一个指定的Item或者Vendor)。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

透视(Perspectives)

当前的Project REAL设计并不包含任何透视。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

定制程序集、用户定义函数(user-defined functions,UDFs)和MDX脚本

当前的Project REAL设计并不包含任何定制程序集、UDFs或者MDX脚本。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

服务器端设置

当前的Project REAL设计没有给便任何服务器端的设置,它们都还保留在默认值上。唯一的一个例外是在我们的一些小型系统上,我们把CoordinatorExecutionMode服务器属性设置成4。这么做的目的是为了在一个CPU或者双CPU的系统上,最多只支持4条并行操作。SQL Server 2005分析服务中,因为它试图并行化多条管理性操作,例如,维度和分割表处理,这些操作在SQL Server 2000分析服务中都是连续的,但现在这可能会带来一些问题。分析服务提供了两种方法用来限制并行化程度。

你能限制在request-by-request基础上限制并行化程度。首先,选择类似维度或者分割表这样的对象。你能在商业智能开发环境(BI Development Studio)和SQL Server管理环境(Management Studio)中选择多个对象,然后按下Ctrl键或者Shift键,用来选择多个条目,完成一个操作。一旦你选择了对象,Process Object(s)对话框就会出现,如图17所示,在单击Change Settings。

Project REAL分析服务技术探讨(1) 

图17:多个对象的并行化处理

然后你能够限制系统,例如,每次最多只能处理4个请求。如图18所示。尽管这个下拉框中的数字是成倍增长的,但你可以随意输入整数值。

Project REAL分析服务技术探讨(1) 

图18:在处理对话框中设置并行化程度

你也能在用来完成处理的XMLA脚本中控制并行化程度。如图19所示。

Project REAL分析服务技术探讨(1)

图19:在XMLA脚本中设置并行化程度

这个方法存在的问题是你不得不在每次处理对象的时候都需要设置它。假如系统中包含太多这样的对象,这将变的很难。例如,处理一个带有231个分割表的Cube就是很困难的。

事实上,假如你通过使用处理对话框将并行化程度设置为8,然后去查看语句的内容,你将看到在XMLA脚本中的MaxParallel属性被设置的值,就是刚才执行的值。

你也能够在服务器端设置最大的并发请求。这在一些场景中会有更好的效果(例如,你不在需要记着每次都设置它)。然而,在其它很多场景中,例如当你正处理小数目的并发请求或者当正执行的SQL语句稍微有点超载的时候,这不会有任何帮助。

改变系统端限制

1.在SQL Server 管理环境中单击服务器,然后选择Properties。

在下面的五个章节中,我们比较和对比了五种使用SQL Server 2005分析服务来模型化实体的方法。我们发现,没有一种简单的方法能够实现所有环境中的关系型模型化。我们发现最好根据运行时可用的存储、所允许的计算来选择使用的方法,从而实现更有弹性的厂商分析模型。

方法#1- 创建单独的真实维度

我们实现的第一种方法是创建了五个真实维度(每个都对应一种厂商类型),并从Item维度表中加载。这种技术很直接,并且很容易实现。然而,它存在一些缺点。首先是它在Cube中带来了一些额外的复杂性。终端用户不得不多使用增加的五个维度。并且在维度存储上也增加了五倍以上(因为每个维度完全不依赖于其它的维度)。最终要的缺点是这种技术不可能实现交叉的厂商分析。例如,考虑“Abrams, Harry N., Inc.”这个厂商。因为Abrams有五个成员,因此无法通过厂商直接的来分离,除非你假定,Abrams在五个维度中都有相同的拼写,并且确保在所有五个维度中都选中这个相同的切片。

方法#2 – 使用属性层次来代替物理维度

这个方法相比于前面的方法,使得货品和厂商之间的关系更加密切。在这种方法中,我们去掉了第一种方法中使用的物理维度,而是在Item维度上添加了五个属性或者用户定义的层次。这五个新的Item层次是:Item.Return Vendor,Item.Purchase Vendor,Item.Original Purchase Vendor,Item.Source Vendor和Item.DC Vendor。使用这种方法,有以下几个优点。首先,因为五个属性是从一个属性键下构建的,因此只需要一个存储位置。第二,因为我们将五个维度转换成五个属性层次(或者用户定义层次),因此这降低了最终Cube的复杂度(维度)。对于一些终端用户,这点很重要,这能使得他们在Cube之间导航更加简单。然而,这种方法也不允许覆盖多个厂商的分析。

方法#3 – 为Vendor和Vendor类型创建多对多的维度

第三个方法是在三个维度(Item, Vendor和 Vendor Type.)之间创建一个多对多的维度,这是一个不常用的方法,这会带来大量的成本。Item维度并没有任何变化。Vendor维度需要在五中类型的厂商上将所有可能的厂商合并(并去除重复的项)。最后,Vendor Type已经有五个成员,分别为Return、Purchase、Original Purchase、Source和DC服务。一旦维度就绪后,就创建一个度量组,用来表示每个Item和它的五中类型。度量组看上去的效果如图21所示。

Project REAL分析服务技术探讨(1) 

图21:一个在Item、Vendor、Vendor Type维度表之间多对多的维度

如同你看到的一样,这个度量组确实非常大。在完整的维度中,我们会有超过六百万个项货品,每项有五种类型,以及约4万个厂商。这意味着,在这个多对多的度量(在Cube设计中被称为Item Vendor)组中,我们会有超过3千万项记录。

这个方法的主要缺点是为了完成对厂商的分析,你必须构建一个在正被分析的分割表数据之间的百万对百万级别的交叉连接和一个多对多的度量组(也包含几百万条记录)。这意味着,在第二种方法中只需要几秒的查询,在这种方法中会慢上许多(例如几十妙)。但是,这种方法也带来了巨大的好处。现在,你可以用一个独立的成员表示一个成员。这能够让成员更容易被区分,并能够直接的比较。如图22所示。

Project REAL分析服务技术探讨(1) 

图22:通过Vendor Type查找一个Vendor的销售情况

这在其它技术中是不可能实现的,除非你手工的把五个切片设置成相同的值。

方法#4 – 使用一个引用或者扮演角色的维度

第四种技术将创建一个单独的Cube维度,被称为Vendor,就像多对多的这种方法一样,它有一个单独的成员,值都是来自于Item维度表中每个被联合的厂商。然后再将这个维度添加到Cube(每次都对应一个角色),作为一个引用或者扮演角色的维度。第一次,Vendor维度被称为Return Vendor;第二个被称为Purchase Vendor;以下类似。虽然这个方法还是具有交叉厂商分析的缺点,但是这种方法只需最小的存储并且实现很直接。

假如你使用这种技术,需要意识到一点,和多对多方法一样,实际的计算是在运行时完成的。在适当的分割表数据和扮演角色维度之间存在一个连接,然后数据就形成了。尽管这种方法存在和多对多一样的性能问题,但这种方法不需要额外的分析能力。

方法#5 – 使用引用或者扮演角色维度并实物化

第五种用来模型化厂商的方法是用第四种方法创建扮演角色维度,但当你指定引用维度的时候,将类型设置成“materialized”。当这个设置生效的时候,会为每个角色产生一个维度的独立拷贝。这能够提高在维度内存成本上的性能(因为不用在运行的时候连接)。

关于厂商模型化的技术总结。

总体上,这五种厂商模型化技术如下所示:

1.实现五个真实的维度,每个都对应一个类型。这增加了维度的数量,但这种方法速度很快,并且集合能够被预先计算。

2.在Item维度中实现五个属性层次。这减少了维度的复杂性以及厂商和Item维度之间的关联(这相比于第一种方法,更加清晰)。方法#1和方法#2一个共同的缺点在于交叉厂商的分析,因为,无论它是什么角色,那里没有一个成员,能够代表一个唯一的维度。

3.实现了一个在Item、Vendor和Vendor Type之间的多对多维度。这种发放速度更慢一些,但是概念上却更加清晰。它允许你无需改变元数据就能添加厂商角色的数目。这使得结构更有伸缩性,并且允许这种交叉厂商的分析。因为这种多对多度量组需要大量的查询时间,因此这是一种速度最慢的方法。

4.使用一个单独的Vendor维度,实现五个引用(或角色扮演)维度。这很容易完成,并且比头两个方法概念更加清晰。由于这种方法是在运行的时候完成的,因此这种方法的性能会受一点影响。并且,没有可以预先计算的真实集合。

5.实现方法#4,并且将角色扮演维度再实物化。这实现起来和方法#4一样容易,但每个维度成员都需要创建来形成。这意味着能够设计集合,并实现预先计算。由于没有单独的成员来表示一个唯一的厂商(无论它是什么角色),和#1、#2一样,方法#4和方法#5都有交叉厂商共有的缺点,然而由于已经存在基础的对象,方法#4和#5相比于方法#1和#2,更加直接。所有你要做的,只是在添加第六、第七个引用或者扮演角色维度。Vendor维度已经准备就绪。但所有的四种方法都需要改变元数据,这将影响到你现有的报表和MDX查询。只有方法#3允许你在无需修改元素据的情况下,添加新的厂商类型。

在Project REAL中,我们实现的是方法#2和#3。我们捆绑了这两种方法,以至于终端用户能够能够权衡是更好的考虑性能还是更好的考虑分析功能,从而选择更适当的方法。

半可加减的存货度量

在Store和DC存活数据中有一个出名的问题。一般,当我们处理像销售总数和销售数量这种多维度的数据时,度量都时可加减的。为了得到WA地区的销售总数,你所要做的就是把所有城市的所有仓库的销售总数加起来。我们把这种计算叫做可加减的(Additive)。SQL Server 2000分析服务支持四种可加减的操作,分别是Sum, Count, Min和Max。这样,平均值就能通过Sum/Count来实现。

例如,图23中Sale Amt 列中的数据代表了Kirkland,WA仓库在某个时段的销售总数。Sum就是为计算Sales Amt的集合函数。

Project REAL分析服务技术探讨(1) 

图23:Kirkland仓库销售和存货数据

注意,每周的销售总数是从每天的总数计算获得,每月的总数是从每周的总数上计算获得。因此我们称总销售是一个可加减的度量。这种方法对On-Hand Qty度量适用么?显然不行。库存的数量、订单数量看上去是一些半可加性的度量。这些需要汇总的值都是基于某个时间段的一个时间点,而不是基于总数,也不是基于最后的值(或者是一些其它基于半可加性的计算)。在这个例子中,在周六统计库存的详细信息。假如在月初,Kirkland仓库书本的数量是10000,库存需要在每周六的时候都保存相同的数量(10000)直到月底(我们假定每周中每售出一本书,都会在周五得到补充),那么我们在月底的时候,存货是40000(总数)还是10000(最后的存活)呢?

为了解决这个问题,我们使用了SQL Server 2005分析服务中一个新的半加性集合函数。由于我们已经具备时间维度,我们所需要做的仅仅是把集合函数从Sum改成LastNonEmpty,这样就能实现我们预期的功能。

由于SQL Server 2000分析服务仅支持可加减的度量,原来在Project REAL设计的复杂计算都必须手工的来完成。现在在SQL Server 2005分析服务中,已经支持半可加性的操作。我们所要做的只是改变集合函数。如图24所示。

Project REAL分析服务技术探讨(1) 

图24:为度量指定集合函数,可以设置成可加性的(左图)或者为半可加性的(右图)

最佳实践:假如你使用半可加性的度量,请确认Cube包含的维度不超过一个。

使用半可加性的度量,有一些约束。首先,你必须有一个被标识为Time类型的维度用来使用半可加性度量。如图25所示。当它运行的时候,时间智能向导(Time Intelligence Wizard)将会合适的设置属性和维度类型属性。假如你通过标准的维度向导(Dimension Wizard)创建你自己的时间维度,你必须再手工的设置适当的类型属性。

Project REAL分析服务技术探讨(1) 

LastNonEmpty函数不能计算所有类型的维度。它只能完成基于时间维度的计算。而且,在Cube中智能包含一个时间维度。假如在你的cube中包含多个时间维度,系统会找到第一个符合要求的去执行。这虽然不是一个必要的、优秀的、可预言的选择,但事实上,它就是这么做的。

结论

这份白皮书提供了一些关于SQL Server 2005分析服务(Analysis Services)的技术性讨论,主要是关于分析服务的设计和Rroject Real项目中的一些实际应用。我们回顾了许多很好的实践和资料,这些都是在Project REAL项目中积累下来的,并提供了各种不同类型对象的信息,例如数据源、数据源视图、维度、层次、属性、度量组和部分。

若要回顾用来同步关系型分割表模式和分析服务(Analysis Services )度量组分割表模式的SQL Server 2005集成服务(Integration Services)程序包,请参见附录A。

更多内容:http://www.microsoft.com/sql/

附录A:自动的分割表创建

Project REAL设计应用了大量的分割。产品系统中有超过220个极大的分割表。范例数据使用了125个以上的分割表,每个表中都只有几万条数据。完整的产品系统在每个分割表中大概会有1.8亿-2.0亿条记录。因为如此多的分割表,每当我们生成一个新的模式时,我们都需要创建一个新的分割表。

因此,就如同谚语所说,“当过程变的基本一致的时候,程序员就需要编写程序了”。

这个附录详细描述了一个SQL Server 2005 Integration Services中的BuildASPartition程序包,这个程序包是为在SQL Server 2005分析服务数据库中自动构建分析服务度量组分割表中而创建的。这个程序包能够同步关系型分割表模式和分析服务(Analysis Services )度量组分割表模式。它循环不断的检查关系型数据库,查找每周生成的实际分割表(通过使用一个表名称转换)。假如找到一个关系型表,它会检查在分析服务度量组中是否存在这个分割表(使用同样的表名称转换)。假如不存在,它会构建一个XMLA脚本,并执行这个脚本,最后生成一个分割表。

图26描述了这个程序包的结构。

Project REAL分析服务技术探讨(1) 

图27描述了它们的变量以及默认值

Project REAL分析服务技术探讨(1) 

图27:BuildASPartition程序包中的变量列表

下表列举了每个变量并解释了如何使用。

变量

角色

Mask

一个用来标识实际表分割表的TSQL LIKE片断。按周的分割表可以的值可以是‘vTbl_Fact_%_WE_%’

注意:LIKE子句中的%符合是一个代表任意字符的通配符,例如:

vTbl_Fact_Store_Sales_WE_2004_11_27

Partition Already There (一个脚本任务)

这个脚本会由两个输出。当分割表不存在的时候,它设置IsNotPresent布尔值变量,并且将构造一个XMLA脚本,用来创建一个分割表(保存到XMLA Script变量中)。

关于这个脚本,需要注意以下几个有趣的地方:

◆它展示了如何引用AMO,并使用它来判断一个分析服务数据库中是否存在一个分割表。

程序包使用如下两种连接对象。

◆AS 数据库

' And then you must add a reference to the assembly in the project

内容目录

关于Project Real 

WHERE SK_Product_ID =

对于查询包含其它产品的分割表,使用如下代码:

SELECT * FROM

)

这种技术,在SQL Server 2000分析服务上,需要大量的管理费用。在SQL Server 2000中,必须给分割表中的每一个成员指定数据切片,即使哪里有几千个成员。为了实现这个例子,你不得不创建一个包含995个成员的分割表。当一个新的成员被添加到维度中的时候,更新这个列表也是管理上面对的一个严峻问题。在SQL Server 2005分析服务中,自动在分割表中构建数据切片的功能大大消除了管理上的成本。

另外面对的一个挑战是,当创建一个带有大量分割表的系统时,如何创建几百个分割表。在SQL Server 2000中,分割表可使用分析管理器(一个非常耗时,并会有潜在错误的过程)创建,而且每次只能创建一个。或者可以让开发人员编写一个应用程序来自动的创建。

在SQL Server 2005中,SQL Server 管理环境能够一次创建多个分割表,甚至是几百个分割表。一般情况下,当你创建一个分割表的时候,你需要使用那些定义在数据源视图中的表。毕竟,这也是数据源视图存在的原因。然而,这也不是必须的。在Store Sales度量组(请确认至少已经提供或者处理了一个分割表)上创建一个分割表,然后检查对话框,如图14所示:

Project REAL分析服务技术探讨(1) 

图14:创建一个新的分割表

注意,虽然对话框默认使用数据源视图,但你也能在数据源中查找和定位表。选择数据源然后单击Find,如图15所示:

Project REAL分析服务技术探讨(1) 

图15:查找一个用于分割的实际表

对话框列举了在数据源中能匹配包含在度量组“模板”表(或视图)的元数据(列和数据类型)的表。见图15。假如你选择了多个条目,系统会为每个选中的表创建分割表。

Project REAL分析服务技术探讨(1) 

图16:选择多个创建分割表的实际表

这回带来两个重要的侧面影响。首先,这意味着,不是所有的对象都来自于数据源视图。在Project REAL中,这意味着我们不必包含所有的23个基于周的分割表。我们只是包含了一个模板对象,用来创建度量组。第二,这也是节约时间的部分,你能够通过一个简单步骤就创建上百个分割表。仅仅只是选择多个对象,你就从一个操作中获得了大量的分割表。只是要求你在这之前已完成至少一个分割表的处理,以至于Find操作能够定位到相匹配的表。也就是这些,我们就可以通过一次点击,就能创建上百个分割表了。

存储方法(Storage method)

在我们的Project REAL工作阶段,所有的分割表都使用MOLAP存储。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

集合和集合设计(Aggregations and aggregation designs)

集合是将被系统计算的subtotal,用来提高检索速度。和集合本身一样,系统也保存了集合的设计。这是集合到底是什么的一种内在表示。设计描述了维度的结合以及应该被计算的subtotal的级别。集合和集合设计被保留在分割表中,这些分割表又都是包含在度量组中。

和SQL Server 2000分析服务将集合设计保存在分割表中不一样的是,在SQL Server 2005分析服务中,集合设计是位于第一位的。假如你查看由数据库提供的XMLA脚本,你会看到集合设计和度量组在相同的级别上。你可以同时有多个集合设计。在一个度量组中,每个分割表都会执行一个它所使用的集合设计。这有以下几种方法:没有集合设计(这也是不必为分割表创建集合的情况);一个针对所有分割表的集合;若干个不同的集合,每个都针对若干个分割表。绝大多数应用程序都使用第一或者第二中方法(要不就不使用集合设计,要么就是所有的分割表都是用一个集合设计)。在一些更复杂的设计中,你可以使用第三种方法(多个集合设计,各自应用于若干个分割表)。例如,你可以在一个当前年的分割表中使用大量的集合,对于最近三年的分割表使用适度的集合,对于三年的分割表,则不使用集合。在脚本上,很容易将一个分割表指向不同的集合设计,只要编辑XMLA脚本即可。

处理设置和错误配置

在度量组中保留分割表的同时,系统也会记录对这些分割表的处理设置和错误配置。对于Store Inventory和DC Inventory度量组,我们可以使用默认的错误配置。这种情况下,当系统检测到无效的外部键或者当它遇到NULL值或者当遇到其它不一致数据时,它会停止处理过程。这是因为默认情况下,系统认为所有的数据都是正确的。

对于Store Sales度量组,我们不得不使用不同的错误配置,假如你还记得在在度量组里面所讨论的,我们讨论了在Customer维度和Store Sales 实际表之间发现的无效数据。由于这是因为数据反馈之间正常的不一致性造成的,因此,我们必须修改默认的错误配置。

Proactive caching设置

考虑MOLAP结构的一种方法是当它被处理的时候,提供一个缓存或者一个关系型数据的图像。SQL Server 2005提供了一个新的功能,能够靠南固执MOLAP缓存什么时候被重新处理。提供了几个你能够改变的几个设置。例如,你可以设置硬编码的时间间隔(例如每隔15分钟)。或者,你能让系统等待数据直到数据被更新后,再处理它。这些设置都是保存在分割表中的。因而,也是保存在度量组中的。在当前的Project REAL系统中,我们使用了自动的MOLAP proactive cache设置。我们计划当我们进行性能测试的时候,再调整这种设置。

其它的Cube对象

除了维度的用法、度量组和分割表,在Cube中还包含了若干其它的对象。这个章节中将简要介绍计算(calculations)、关键性能指示器(KPIs)以及其它存储在Project REAL Cube中的对象。

计算(Calculations)

在当前的Project REAL系统上实现了多个为商业度量服务的计算。例如,计算平均销售数量和库存数量。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

关键性能指示器(Key Performance Indicators,KPIs)

在当前的Project REAL设计上还没有包含关键性能指示器(Key Performance Indicators,KPIs)。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

活动(Actions)

当前的Project REAL设计只包含了一个活动。这个活动被用来作为分析服务客户端和报表服务之间的一个桥梁。这个单元级别的活动,当被终端用户选择的时候,它调用一个报表服务的报表,并传递给报表适当的内容作为参数(例如一个指定的Item或者Vendor)。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

透视(Perspectives)

当前的Project REAL设计并不包含任何透视。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

定制程序集、用户定义函数(user-defined functions,UDFs)和MDX脚本

当前的Project REAL设计并不包含任何定制程序集、UDFs或者MDX脚本。尽管我们正在正规测试的基础上不断扩展我们地测试工作,但我们现在还没有积极地测试这个领域。

服务器端设置

当前的Project REAL设计没有给便任何服务器端的设置,它们都还保留在默认值上。唯一的一个例外是在我们的一些小型系统上,我们把CoordinatorExecutionMode服务器属性设置成4。这么做的目的是为了在一个CPU或者双CPU的系统上,最多只支持4条并行操作。SQL Server 2005分析服务中,因为它试图并行化多条管理性操作,例如,维度和分割表处理,这些操作在SQL Server 2000分析服务中都是连续的,但现在这可能会带来一些问题。分析服务提供了两种方法用来限制并行化程度。

你能限制在request-by-request基础上限制并行化程度。首先,选择类似维度或者分割表这样的对象。你能在商业智能开发环境(BI Development Studio)和SQL Server管理环境(Management Studio)中选择多个对象,然后按下Ctrl键或者Shift键,用来选择多个条目,完成一个操作。一旦你选择了对象,Process Object(s)对话框就会出现,如图17所示,在单击Change Settings。

Project REAL分析服务技术探讨(1) 

图17:多个对象的并行化处理

然后你能够限制系统,例如,每次最多只能处理4个请求。如图18所示。尽管这个下拉框中的数字是成倍增长的,但你可以随意输入整数值。

Project REAL分析服务技术探讨(1) 

图18:在处理对话框中设置并行化程度

你也能在用来完成处理的XMLA脚本中控制并行化程度。如图19所示。

Project REAL分析服务技术探讨(1)

图19:在XMLA脚本中设置并行化程度

这个方法存在的问题是你不得不在每次处理对象的时候都需要设置它。假如系统中包含太多这样的对象,这将变的很难。例如,处理一个带有231个分割表的Cube就是很困难的。

事实上,假如你通过使用处理对话框将并行化程度设置为8,然后去查看语句的内容,你将看到在XMLA脚本中的MaxParallel属性被设置的值,就是刚才执行的值。

你也能够在服务器端设置最大的并发请求。这在一些场景中会有更好的效果(例如,你不在需要记着每次都设置它)。然而,在其它很多场景中,例如当你正处理小数目的并发请求或者当正执行的SQL语句稍微有点超载的时候,这不会有任何帮助。

改变系统端限制

1.在SQL Server 管理环境中单击服务器,然后选择Properties。

结论

这份白皮书提供了一些关于SQL Server 2005分析服务(Analysis Services)的技术性讨论,主要是关于分析服务的设计和Rroject Real项目中的一些实际应用。我们回顾了许多很好的实践和资料,这些都是在Project REAL项目中积累下来的,并提供了各种不同类型对象的信息,例如数据源、数据源视图、维度、层次、属性、度量组和部分。

若要回顾用来同步关系型分割表模式和分析服务(Analysis Services )度量组分割表模式的SQL Server 2005集成服务(Integration Services)程序包,请参见附录A。

更多内容:http://www.microsoft.com/sql/

附录A:自动的分割表创建

Project REAL设计应用了大量的分割。产品系统中有超过220个极大的分割表。范例数据使用了125个以上的分割表,每个表中都只有几万条数据。完整的产品系统在每个分割表中大概会有1.8亿-2.0亿条记录。因为如此多的分割表,每当我们生成一个新的模式时,我们都需要创建一个新的分割表。

因此,就如同谚语所说,“当过程变的基本一致的时候,程序员就需要编写程序了”。

这个附录详细描述了一个SQL Server 2005 Integration Services中的BuildASPartition程序包,这个程序包是为在SQL Server 2005分析服务数据库中自动构建分析服务度量组分割表中而创建的。这个程序包能够同步关系型分割表模式和分析服务(Analysis Services )度量组分割表模式。它循环不断的检查关系型数据库,查找每周生成的实际分割表(通过使用一个表名称转换)。假如找到一个关系型表,它会检查在分析服务度量组中是否存在这个分割表(使用同样的表名称转换)。假如不存在,它会构建一个XMLA脚本,并执行这个脚本,最后生成一个分割表。

图26描述了这个程序包的结构。

Project REAL分析服务技术探讨(1) 

图27描述了它们的变量以及默认值

Project REAL分析服务技术探讨(1) 

图27:BuildASPartition程序包中的变量列表

下表列举了每个变量并解释了如何使用。

变量

角色

Mask

一个用来标识实际表分割表的TSQL LIKE片断。按周的分割表可以的值可以是‘vTbl_Fact_%_WE_%’

注意:LIKE子句中的%符合是一个代表任意字符的通配符,例如:

vTbl_Fact_Store_Sales_WE_2004_11_27

' And then you must add a reference to the assembly in the project
Imports Microsoft.AnalysisServices

Public Class ScriptMain

Public Sub Main()

' Get Server and Database name from DTS connection object
Dim oConn As ConnectionManager
oConn = Dts.Connections("AS database")
Dim sServer As String = _
CStr(oConn.Properties("ServerName").GetValue(oConn))
Dim sDatabase As String = _
CStr(oConn.Properties("InitialCatalog").GetValue(oConn))

' By convention, we know that the database, data source and
' cube are the same name
Dim sDataSource As String = sDatabase
Dim sCube As String = sDatabase
Dim oTable As Variable = Dts.Variables("Table")
Dim sTable As String = CStr(oTable.Value)
Dim sPartition As String = GetPartition(sTable)
Dim sMeasureGroup As String = GetMeasureGroup(sTable)

' We have all of the information about the partition -- use AMO
' to see if it is present. Save in a variable for later reference
Dts.Variables("IsNotPresent").Value = _
Not IsPartitionThere(sServer, sDatabase, sCube, _
sMeasureGroup, sPartition)

' Generate and save the XMLA script (will be executed in a
' Execute Analysis Services DDL task later on). Save in a
' variable for later reference
Dim sXMLA As String = GenerateXMLAScript(sDatabase, sDataSource, _
sCube, sMeasureGroup, sPartition, sTable)
Dts.Variables("XMLA_Script").Value = sXMLA
MsgBox(sXMLA, MsgBoxStyle.OkOnly, "XMLA Script")

Dts.TaskResult = Dts.Results.Success

End Sub

Private Function GetMeasureGroup(ByVal sMG As String) As String

' All tables are in the format: vTbl_Fact__WE_YYYY_MM_DD
'   e.g. vTbl_Fact_Store_Sales_WE_2003_12_27
' Measure group names (from this) are: , e.g. Store Sales
'   and the name may have embedded undorscores (_) which need to
'   be replaced with spaces
Dim i_WE_location As Integer = InStr(sMG, "_WE_")
Dim i_FACT_location As Integer = Len("vTbl_Fact_")
sMG = Left(sMG, i_WE_location - 1)
sMG = Right(sMG, (Len(sMG) - i_FACT_location))
sMG = Replace(sMG, "_", " ")

Return sMG

End Function

Private Function GetPartition(ByVal sPart As String) As String

' All tables are in the format: vTbl_Fact__WE_YYYY_MM_DD
'   e.g. vTbl_Fact_Store_Sales_WE_2003_12_27
' Partition names (from this) are: WE YYYY MM DD,
'   e.g. Store Sales WE 2003 12 27
'   and the name may have embedded undorscores (_) which need to
'   be replaced with spaces
Dim i_FACT_location As Integer = Len("vTbl_Fact_")
sPart = Right(sPart, (Len(sPart) - i_FACT_location))
sPart = Replace(sPart, "_", " ")

Return sPart

End Function

Public Function GenerateXMLAScript(ByVal sDatabase As String, _
ByVal sDataSource As String, ByVal sCube As String, _
ByVal sMeasureGroup As String, ByVal sPartition As String, _
ByVal sTable As String) As String

Dim sX As String
sX = ""

'
' XMLA script is missing the following clauses:
' 1) annotations (not needed)
' 2) physical storage, e.g. proactive caching settings, etc.
'        Note: not needed since default values used
' 3) linkage to aggregation designs (TBD) -- we need a management
'        utility to control aggregation usage
'
' Note: because of quoting rules conflict between VB.NET and
'       XMLA scripts, all double-quotes (") are replaced with
'       uparrows (^)
'

sX = sX & "sX = sX & "analysisservices/2003/engine^>" & vbCrLf
sX = sX & "    " & vbCrLf
sX = sX & "        " & sDatabase & _
"
" & vbCrLf
sX = sX & "        " & sCube & "" & vbCrLf
sX = sX & "        " & sMeasureGroup & _
"
" & vbCrLf
sX = sX & "   
" & vbCrLf
sX = sX & "    " & vbCrLf
sX = sX & "        sX = sX & "2001/XMLSchema^ xmlns:xsi=^http://www.w3.org/2001/"
sX = sX & "XMLSchema-instance^>" & vbCrLf
sX = sX & "            " & sPartition & "" & vbCrLf
sX = sX & "            " & sPartition & "" & vbCrLf
sX = sX & "            " & vbCrLf
sX = sX & "                " & sDataSource & _
"
" & vbCrLf
sX = sX & "                dbo" & _
vbCrLf
sX = sX & "                " & sTable & _
"
" & vbCrLf
sX = sX & "            " & vbCrLf
sX = sX & "       
" & vbCrLf
sX = sX & "   
" & vbCrLf
sX = sX & "
" & vbCrLf
sX = sX & " " & vbCrLf

' replace all up-arrows with double-quotes
sX = Replace(sX, "^", """")

Return sX

End Function

Public Function IsPartitionThere(ByVal sServer As String, _
ByVal sDatabase As String, ByVal sCube As String, _
ByVal sMeasureGroup As String, _
ByVal sPartition As String) As Boolean

' By default, we will assume that it isn't there
' Only if we get all of the way to the end and everything is
' found, will we set it true
Dim bIsPartitionThere As Boolean = False

Dim oServer As New Microsoft.AnalysisServices.Server
' connect to the server and start scanning down the
' object hierarchy
oServer.Connect(sServer)

Dim oDB As Database = oServer.Databases.FindByName(sDatabase)
If oDB Is Nothing Then
MsgBox("Did not find expected database: " & sDatabase, _
MsgBoxStyle.OkOnly, "Error looking for partition")
GoTo Done
Else
Dim oCube As Cube = oDB.Cubes.FindByName(sCube)
If oCube Is Nothing Then
MsgBox("Did not find expected cube: " & sCube, _
MsgBoxStyle.OkOnly, "Error looking for partition")
GoTo Done
Else
Dim oMG As MeasureGroup = _
oCube.MeasureGroups.FindByName(sMeasureGroup)
If oMG Is Nothing Then
MsgBox("Did not find expected Measure Group: " & _
sMeasureGroup, _
MsgBoxStyle.OkOnly, _
"Error looking for partition")
GoTo Done
Else
'-- This is the real test -- to see if the partition
'   is really there
Dim oPart As Partition = _
oMG.Partitions.FindByName(sPartition)
If Not oPart Is Nothing Then
' This is the only place to set the value to TRUE
bIsPartitionThere = True
End If
End If
End If
End If

Done:
oServer.Disconnect() ' disconnect from the server -- we are done

NoConnection:
Return bIsPartitionThere
End Function
End Class