<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>简单生活 -- Kevin Yang的博客 &#187; 性能优化</title>
	<atom:link href="http://www.imkevinyang.com/tags/%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imkevinyang.com</link>
	<description>It&#039;s all about sharing</description>
	<lastBuildDate>Sun, 05 Feb 2012 15:37:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Analysis Services：你应该使用多对多维度吗？</title>
		<link>http://www.imkevinyang.com/2010/04/analysis-services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html</link>
		<comments>http://www.imkevinyang.com/2010/04/analysis-services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html#comments</comments>
		<pubDate>Sun, 11 Apr 2010 17:29:58 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[BI/数据库]]></category>
		<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[多对多]]></category>
		<category><![CDATA[度量组]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[维度]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/04/analysis-services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html</guid>
		<description><![CDATA[如果你是一个初学者，请注意，这篇文章并不是告诉你不要在Analysis Services中使用多对多（m:n）维度。事实上，这是一个非常棒的功能，它允许你将多个维度成员和多条事实数据之间建立关联关系。在很多商业领域，从零售行业到会计行业到医疗行业，多对多关系被大量使用着。但有时在处理多对多关系时，如果遇到大规模数据量，可能会遇到数据查询性能问题以及数据精准性问题。这篇技术文章就是为了说明多对多关系背后的工作原理和适合的商业应用场景，以及应用多对多关系可能带来的数据精准性问题。]]></description>
			<content:encoded><![CDATA[<div class="statement">
<p>作者：Denny Lee</p>
<p>译者：<a href="http://www.imkevinyang.com/2010/04/Analysis%20Services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html">Kevin Yang</a></p>
<p>英文链接：<a title="http://sqlcat.com/technicalnotes/archive/2008/02/11/analysis-services-should-you-use-many-to-many-dimensions.aspx" href="http://sqlcat.com/technicalnotes/archive/2008/02/11/analysis-services-should-you-use-many-to-many-dimensions.aspx">http://sqlcat.com/technicalnotes/archive/2008/02/11/analysis-services-should-you-use-many-to-many-dimensions.aspx</a></p>
</div>
<p>如果你是一个初学者，请注意，这篇文章并不是告诉你不要在Analysis Services中使用多对多（m:n）维度。事实上，这是一个非常棒的功能，它允许你将多个维度成员和多条事实数据之间建立关联关系。在很多商业领域，从零售行业到会计行业到医疗行业，多对多关系被大量使用着。但有时在处理多对多关系时，如果遇到大规模数据量，可能会遇到数据查询性能问题以及数据精准性问题。这篇技术文章就是为了说明多对多关系背后的工作原理和适合的商业应用场景，以及应用多对多关系可能带来的数据精准性问题。</p>
<h2>相关背景</h2>
<p>我在我之前的博文“<a href="http://denster.spaces.live.com/blog/cns%21125D53A08EC75357%21283.entry">How to handle many-to-many relationships in Yukon?</a>”中提到的应用多对多关系的一个例子是地理维度。但现在我们将使用Adventure Works DW OLAP这个示例（相关代码在Codeplex的<a href="http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004">SQL Server 2005 SP2 Sample Databases</a>上可以下载到）。</p>
<p>打开AdventureWorks数据库，在AdventureWorks数据立方体的“维度使用”标签卡下，我们可以看到[Sales Reason]维度通过[Sales Reasons]中间度量组关联到了[Internet Sales]度量组（图中没有显示）上。[Sales Reasons]旁边放了一个数学上用于表示“无穷”的图标，说明这个关系和常规维度（就像[Source Currency]维度和[Source Currency Code]度量组的关系）不一样，这是一个多对多关系。</p>
<p><a href="http://sqlcat.com/blogs/technicalnotes/WindowsLiveWriter/AnalysisServicesShouldyouusemanytomanydi_8E4E/image_2.png"><img style="display: inline; border: 0px;" title="在BIDS中[Sales Reason]和[Internet Sales]的多对多关系图" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/clip_image001.png" border="0" alt="在BIDS中[Sales Reason]和[Internet Sales]的多对多关系图" width="351" height="71" /></a></p>
<p>单击[Sales Reasons]度量组，会弹出一个设计维度-度量组关联的对话框（见下图），在这里，你会注意到，[Sales Reason]和[Internet Sales]这两者之间的关系是多对多关系，并且，连接[Sales Reason]维度和[Internet Sales]度量组的中间度量组是[Sales Reasons]。</p>
<p><a href="http://sqlcat.com/blogs/technicalnotes/WindowsLiveWriter/AnalysisServicesShouldyouusemanytomanydi_8E4E/image_4.png"><img style="display: inline; border: 0px;" title="在BIDS中设计多对多关系" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/clip_image002.png" border="0" alt="在BIDS中设计多对多关系" width="461" height="272" /></a></p>
<p>以下这张图说明了在这个场景中使用多对多维度的目的。我们希望把多个销售成功因素（例如价格很低，展示效果不错，或者其他因素）和一笔销售订单关联起来。</p>
<p><a href="http://sqlcat.com/blogs/technicalnotes/WindowsLiveWriter/AnalysisServicesShouldyouusemanytomanydi_8E4E/image_6.png"><img style="display: inline; border: 0px;" title="销售因素和销售情况之间的维度-度量组关系图" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/clip_image003.png" border="0" alt="销售因素和销售情况之间的维度-度量组关系图" width="382" height="195" /></a></p>
<p>举个例子，John购买了一个高清电视机（对应事实表Internet Sales的一条记录），是因为最近正在大减价（销售成功因素：价格）并且超级联赛杯快要开始了（销售成功因素：其他）。</p>
<h2>应用场景示例</h2>
<p>我们回过头来看看[Adventure Works]的Sql以及Olap数据库的设计，这样可以更好地从技术上去理解多对多关系。在之前我们看到的[Adventure Works DW]Olap数据库中包含了[Internet Sales]和[Sales Reasons]度量组，以及[Sales Reason]维度。在AdventureWorks的Sql数据库中，这几个对象分别对应着FactInternetSales、FactInternetSalesReasons以及DimSalesReason表。</p>
<p>继续我们上面的例子，为了简单起见，我们只关注两条数据(SalesOrderNumber = 'SO69868', SalesOrderLineNumber = 2) 和(SalesOrderNumber = 'SO75088', SalesOrderLineNumber = 3)。</p>
<p>Sql查询为：</p>
<pre class="csharpcode"><span class="kwrd">select</span> SalesOrderNumber, SalesOrderLineNumber, SalesAmount
<span class="kwrd">from</span> FactInternetSales
<span class="kwrd">where</span> (SalesOrderNumber = <span class="str">'SO69868'</span> <span class="kwrd">and</span> SalesOrderLineNumber = 2) <span class="kwrd">or</span>
(SalesOrderNumber = <span class="str">'SO75088'</span> <span class="kwrd">and</span> SalesOrderLineNumber = 3)</pre>
<p>结果集：</p>
<p><img style="display: inline; border: 0px;" title="两笔订单交易数据" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image.png" border="0" alt="两笔订单交易数据" width="305" height="66" /></p>
<p>当你开始考虑FactInternetSales和FactInternetSalesReasons的多对多关系，需要将SalesReason表也加进来，你需要执行以下Sql查询：</p>
<pre class="csharpcode"><span class="kwrd">select</span> a.SalesOrderNumber, a.SalesOrderLineNumber, a.SalesAmount,
c.SalesReasonKey, c.SalesReasonName, c.SalesReasonReasonType
<span class="kwrd">from</span> FactInternetSales a
<span class="kwrd">inner</span> <span class="kwrd">join</span> FactInternetSalesReason b
<span class="kwrd">on</span> b.SalesOrderNumber = a.SalesOrderNumber
<span class="kwrd">and</span> b.SalesOrderLineNumber = a.SalesOrderLineNumber
<span class="kwrd">inner</span> <span class="kwrd">join</span> DimSalesReason c
<span class="kwrd">on</span> c.SalesReasonKey = b.SalesReasonKey
<span class="kwrd">where</span> (a.SalesOrderNumber = <span class="str">'SO69868'</span> <span class="kwrd">and</span> a.SalesOrderLineNumber = 2) <span class="kwrd">or</span>
(a.SalesOrderNumber = <span class="str">'SO75088'</span> <span class="kwrd">and</span> a.SalesOrderLineNumber = 3)</pre>
<p>新的结果集如下：</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image1.png" border="0" alt="image" width="566" height="82" /></p>
<p>从这两张表中你也可以看出，通过中间表FactInternetSalesReasons，你可以将多条销售成功因素记录关联到同一笔销售订单上。例如上述的SO75088订单，金额为$34.99，关联着“价格”和“其他”两条销售成功因素记录。</p>
<h2>多对多维度的优势</h2>
<p>这种通过中间表关联的优势在于，你可以将多个维度成员和一个事实表记录关联到一起。当你想要汇总这些值的时候，优势就体现出来了。例如，当你使用[Sales Reason]维度去查询[Internet Sales]度量组的时候，可以得到以下结果：</p>
<pre class="csharpcode"><span class="kwrd">select</span> {[Measures].[Internet Sales Amount]} <span class="kwrd">on</span> columns,
{[Sales Reason].[Sales Reason].members} <span class="kwrd">on</span> <span class="kwrd">rows</span>
<span class="kwrd">from</span> [Adventure Works]</pre>
<p><img style="display: inline; border: 0px;" title="不同销售成功因素对于销售的影响" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image2.png" border="0" alt="不同销售成功因素对于销售的影响" width="416" height="259" /></p>
<p>上述结果集里头，由于[Price]和[Others]这两个销售成功因素都是SO75088这个订单成功的因素，因此其销售额都包含了SO75088订单的金额。而更不错的是，你现在有了一个[All Sales Reasons]的成员，用来表示总的销售金额$29,358,677.22。</p>
<p>你如果直接查询[Measures].[Internet Sales Amount]指标，得到的结果也是一样的。</p>
<pre class="csharpcode"><span class="kwrd">select</span> {[Measures].[Internet Sales Amount]} <span class="kwrd">on</span> columns
<span class="kwrd">from</span> [Adventure Works]</pre>
<h2>数据精准性问题</h2>
<p>使用多对多维度的一个潜在问题就是数据重复计算，特别是当用户没能很好理解多对多背后原理的话，更有可能出现这种情况。例如，我们执行以下MDX查询：</p>
<pre class="csharpcode"><span class="kwrd">select</span> {[Measures].[Internet Sales Amount]} <span class="kwrd">on</span> columns,
{[Sales Reason].[Sales Reason].children} <span class="kwrd">on</span> <span class="kwrd">rows</span>
<span class="kwrd">from</span> [Adventure Works]</pre>
<p>得到以下结果：</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image3.png" border="0" alt="image" width="383" height="235" /></p>
<p>得到这样的数据之后，用户可能会直接使用上述的数据相加来计算总的销售金额，从而得到以下结果：</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image4.png" border="0" alt="image" width="385" height="256" /></p>
<p>注意，这里的总和$30,856,531.52和前面提到的[All Sales Reasons]成员的汇总值$29,358,677.22很不一样，相差了$1,497,854.30，如果你从事金融方面工作的话，这个差别应该是足够明显了。</p>
<p>问题的复杂之处在于，当你应用多对多维度的时候，你无从知道那些成员会被重复计算，因为任何一单销售都有可能和任何一个销售成功因素关联。例如用户有可能直接把[Other]和[Price]成员的销售额相加，得到因为这两个原因而成交的订单销售额情况$11,224,325.90。但是这样的结果是错误的，因为有一些销售订单同时包含了这两个销售成功因素。因此总和应该是小于$11,224,325.90的。</p>
<h2>有别的解决办法吗？</h2>
<p>“是否应该使用多对多维度”，你主要需要考虑两个方面的问题：性能和数据精准性。</p>
<h3>性能</h3>
<p>在<a href="http://download.microsoft.com/download/8/5/e/85eea4fa-b3bb-4426-97d0-7f7151b2011c/ssas2005perfguide.doc">Analysis Services 性能指南</a>中提到，有时候应用多对多是出于性能的考虑，其中一个情形就是对Distinct Count类型的度量进行泛化。使用多对多维度可以让你通过Analysis Services的sum、count、max、min等运算符实现和Distinct Count一样的逻辑。为了计算Distinct Count或者Sum，Analysis Services存储引擎需要直接对最小粒度的数据做转换。这是因为，当一个查询涉及到多对多维度的时候，聚合结果是在查询期间通过目标度量组和中间度量组在属性级别上完成的。查询的过程相对比较消耗CPU和内存。</p>
<p>多对多的性能考虑主要包括以下几个方面：</p>
<ul>
<li>因为查询涉及到多对多维度，会在目标度量分组和中间度量分组之间生成一个Join连接，因此降低中间度量组的表大小（通常小于1百万行数据）可以提高查询性能。细节参考：<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=3494E712-C90B-4A4E-AD45-01009C15C665&amp;displaylang=en">Analysis Services Many-to-Many Dimensions: Query Performance Optimization Techniques</a> 白皮书。</li>
<li>目标度量组和中间度量组之间的连接是哈希连接，因此完成此项操作非常消耗内存。</li>
<li>和Distinct Count不同，多对多关系不能被预聚合（虽然通常对于Distinct Count来说，要设计通用的预聚合也不是一件容易的事）。因此，涉及到多对多维度的查询无法使用预聚合或者聚合缓存，除非直接命中才有效。不过在几种特殊情形下多对多关系还是有可能被预聚合的，详细信息参考：Analysis Services Many-to-Many Dimensions: Query Performance Optimization 技术白皮书。</li>
<li>因为多对多无法被预聚合，很多MDX计算例如VisualTotals，subselects和Create Subcube都会遇到问题。</li>
</ul>
<h3>数据精准性</h3>
<p>正如你在“数据精准性问题”这一节中看到的，在应用多对多关系的场景中你可能会得不到期望的值（例如重复计算）。所以，即便这是一项非常强大的功能，如果用户没有认识到背后的多对多关系，他可能会得到错误的结果。</p>
<h2>分析</h2>
<p>你可以参考Marco Russo写的<a title="Many-to-many维度建模" href="http://www.sqlbi.eu/Default.aspx?tabid=80" target="_blank">Many-to-many维度建模</a>，里头提及了很多基于多对多维度关系之上建模的解决方案。对于数据仓库以及商业智能问题来说，“是否应该使用多对多维度”这个问题，不存在一个绝对的答案。重要的是，你在实际应用之前，首先需要理解多对多背后的含义。</p>
<p>在 [Sales Reason]这个示例中，有多种情况可以判断是否应该使用多对多维度：</p>
<h3>你想要多对多关系，并且经常会使用Sales Reason维度去剖析数据。</h3>
<p>如果你经常需要使用Sales Reason维度去剖析数据，那么你其实并不需要一个中间度量组。在这个场景中，你可以将[FactInternetSales]和[FactInternetSalesReason]表合成一张新的事实表，然后基于这张表上建立新的数据立方体。因为你经常需要使用sales reason维度去剖析数据，当你使用[Price]成员去剖析数据的时候，以下高亮的行会被选中：</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image5.png" border="0" alt="image" width="546" height="81" /></p>
<p>如果你选择了[Other]成员来剖析的话，以下高亮的行会被选中：</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image6.png" border="0" alt="image" width="539" height="79" /></p>
<p>如果你想要获取汇总值，例如总销售额，你可以基于FactInternetSales表建立新的数据立方体，这样就不需要通过中间度量分组。</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image7.png" border="0" alt="image" width="303" height="68" /></p>
<h3>你实际上并不需要多对多关系</h3>
<p>在我们这个场景中，实际上根本并不需要多对多关系。想想看，事实上，我们只需要规定，每笔销售订单只允许有一个销售成功因素即可。</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image8.png" border="0" alt="image" width="464" height="34" /></p>
<p>或</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image9.png" border="0" alt="image" width="467" height="35" /></p>
<p>另外一种处理办法是将此订单的销售额分摊到不同的销售成功因素上。</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/04/image10.png" border="0" alt="image" width="486" height="51" /></p>
<h2>结论</h2>
<p>注意，以上说的这些并不是要告诉你，不要去使用多对多维度。这是一项非常棒的功能，它让用户能够实现他们想要的效果——将多个维度成员关联到同一个事实表记录上，同时在计算总和的时候又不会出现重复计算的问题。但需要注意，使用多对多维度对于汇总值的影响（例如，将所有单元格的值汇总起来并不总是等于实际的总值）还有它对于其他维度的影响。同时，还需要考虑性能方面的问题，虽然在<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=3494E712-C90B-4A4E-AD45-01009C15C665&amp;displaylang=en">Analysis Services Many-to-Many Dimensions: Query Performance Optimization </a>技术白皮书中已经对如何优化多对多的查询性能做出了指导。在处理多对多问题上还有其他的解决方案，所以请确保你已经考虑过这些解决方案，并且已经理解了多对多的潜在问题。</p>
<p style="text-align: right;">——<a title="Analysis Services：你应该使用多对多维度吗？" href="http://www.imkevinyang.com/2010/04/Analysis%20Services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/analysis-services" title="Analysis Services" rel="tag">Analysis Services</a>, <a href="http://www.imkevinyang.com/categories/techarticles/businessintelligence" title="BI/数据库" rel="tag">BI/数据库</a>, <a href="http://www.imkevinyang.com/tags/olap" title="OLAP" rel="tag">OLAP</a>, <a href="http://www.imkevinyang.com/tags/%e5%a4%9a%e5%af%b9%e5%a4%9a" title="多对多" rel="tag">多对多</a>, <a href="http://www.imkevinyang.com/tags/%e5%ba%a6%e9%87%8f%e7%bb%84" title="度量组" rel="tag">度量组</a>, <a href="http://www.imkevinyang.com/tags/%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96" title="性能优化" rel="tag">性能优化</a>, <a href="http://www.imkevinyang.com/tags/%e7%bb%b4%e5%ba%a6" title="维度" rel="tag">维度</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2010/05/64%e4%bd%8d%e7%b3%bb%e7%bb%9f%e4%b8%8biis7-isapi%e5%a4%84%e7%90%86%e5%99%a8%e5%8a%a0%e8%bd%bd%e5%a4%b1%e8%b4%a5.html" title="64位系统下IIS7 ISAPI处理器加载失败 (2010/05/05)">64位系统下IIS7 ISAPI处理器加载失败</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/analysis-service-2005-olap-best-practice-white-paper.html" title="Analysis Service 2005 OLAP Best Practice White Paper (2009/05/22)">Analysis Service 2005 OLAP Best Practice White Paper</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/analysis-services-2005-olap%e8%ae%be%e8%ae%a1%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5.html" title="Analysis Services 2005 OLAP设计最佳实践 (2009/04/02)">Analysis Services 2005 OLAP设计最佳实践</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/bids%e5%af%b9%e4%ba%8e%e7%bb%b4%e5%ba%a6%e5%b1%9e%e6%80%a7%e9%94%ae%e4%b8%ba%e5%8f%af%e5%8f%98%e9%95%bf%e5%88%97%e6%97%b6%e5%ad%98%e5%9c%a8%e7%9a%84bug.html" title="BIDS对于维度属性键为可变长列时存在的Bug (2009/03/22)">BIDS对于维度属性键为可变长列时存在的Bug</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/bids%e9%83%a8%e7%bd%b2%e6%97%b6%e5%87%ba%e7%8e%b0%e5%85%83%e6%95%b0%e6%8d%ae%e7%ae%a1%e7%90%86%e5%99%a8%e5%8f%91%e7%94%9f%e9%94%99%e8%af%af.html" title="BIDS部署时出现元数据管理器发生错误 (2009/03/13)">BIDS部署时出现元数据管理器发生错误</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/01/google-analytics%e4%b8%ad%e7%9a%84page%e7%bb%b4%e5%ba%a6.html" title="Google Analytics中的Page维度 (2010/01/04)">Google Analytics中的Page维度</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/08/olap%e4%b8%ad%e7%9a%84averageofchildren%e8%81%9a%e5%90%88%e6%96%b9%e5%bc%8f.html" title="OLAP中的AverageOfChildren聚合方式 (2009/08/10)">OLAP中的AverageOfChildren聚合方式</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/ssas%e5%a4%84%e7%90%86%e6%97%b6%e6%89%be%e4%b8%8d%e5%88%b0%e5%b1%9e%e6%80%a7%e9%94%ae%e7%9a%84%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95.html" title="SSAS处理时&ldquo;找不到属性键&rdquo;的解决办法 (2010/07/19)">SSAS处理时&ldquo;找不到属性键&rdquo;的解决办法</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/10/%e5%85%a8%e5%8d%8a%e8%a7%92%e7%a9%ba%e6%a0%bc%e5%af%bc%e8%87%b4%e7%9a%84analysis-service%e5%a4%84%e7%90%86%e9%94%99%e8%af%af.html" title="全半角空格导致的Analysis Services处理错误 (2009/10/09)">全半角空格导致的Analysis Services处理错误</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/%e6%9d%83%e9%99%90%e5%af%bc%e8%87%b4%e7%9a%84analysis%e6%80%a7%e8%83%bd%e8%ae%a1%e6%95%b0%e5%99%a8%e5%9c%a8vistawin2008%e4%b8%8b%e5%a4%b1%e6%95%88%e7%9a%84%e9%97%ae%e9%a2%98.html" title="权限不足导致的Analysis性能计数器在Vista/win2008下失效的问题 (2009/11/12)">权限不足导致的Analysis性能计数器在Vista/win2008下失效的问题</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/04/analysis-services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Analysis Service 2005 OLAP Best Practice White Paper</title>
		<link>http://www.imkevinyang.com/2009/05/analysis-service-2005-olap-best-practice-white-paper.html</link>
		<comments>http://www.imkevinyang.com/2009/05/analysis-service-2005-olap-best-practice-white-paper.html#comments</comments>
		<pubDate>Fri, 22 May 2009 13:21:40 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[BI/数据库]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[多维数据集]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[性能指南]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[维度设计]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/05/analysis-service-2005-olap-best-practice-white-paper.html</guid>
		<description><![CDATA[<font size="1">Data Source Design Best Practices</font>
<p><font size="1" face="Arial">OLAP databases in Analysis Services 2005 have several special requirements that are important to ensure trouble-free access to source data.</font></p>
<font size="1">D&#8230;</font>]]></description>
			<content:encoded><![CDATA[<h5><font size="1">Data Source Design Best Practices</font></h5>
<p><font size="1" face="Arial">OLAP databases in Analysis Services 2005 have several special requirements that are important to ensure trouble-free access to source data.</font></p>
<h6><font size="1">Do use only supported OLEDB providers in a Data Source</font></h6>
<p><font size="1" face="Arial">Analysis Services was designed and tested to work with a specific set of OLE DB providers. Although other OLE DB providers are available, and the Data Source Wizard lets you choose any compatible provider, the capabilities and behavior of different providers can differ substantially. This is true even for different providers that connect to the same database. Therefore, you should use only the supported providers.&#160; For a list of officially supported providers, see </font><font size="1" face="Arial">http://msdn2.microsoft.com/en-us/library/ms175608.aspx</font><font size="1" face="Arial">.</font></p>
<h6><font size="1">Do not use the .Net SqlClient Data Provider to connect to a SQL Server data source</font></h6>
<p><font size="1" face="Arial">Because the Analysis Services server runs in native code, you can get better performance by using a native provider. Therefore, do not use the .Net SqlClient Data Provider; instead, use the Microsoft OLE DB Provider for SQL Server or the SQL Native Client provider.</font></p>
<p><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"></a><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"><font size="1" face="Arial">Top Of Page</font></a></p>
<h5><font size="1">Dimension Design Best Practices</font></h5>
<p><font size="1" face="Arial">Good dimension design is the most important aspect of a well designed Analysis Services OLAP database. Although the wizards in Analysis Services do much of the work to get you started, it is important to review the design that is created by the wizard and ensure that the attributes, relationships, and hierarchies correctly reflect the data and match the needs of your end-users.</font></p>
<h6><font size="1">Do create attribute relationships wherever they exist in the data</font></h6>
<p><font size="1" face="Arial">Attribute relationships are an important part of dimension design.&#160; They help the server optimize storage of data, define referential integrity rules within the dimension, control the presence of member properties, and determine how MDX restrictions on one hierarchy affect the values in another hierarchy.&#160; For these reasons, it is important to spend some time defining attribute relationships that accurately reflect relationships in the data.</font></p>
<h6><font size="1">Avoid creating attributes that will not be used</font></h6>
<p><font size="1" face="Arial">Attributes add to the complexity and storage requirements of a dimension, and the number of attributes in a dimension can significantly affect performance.&#160; This is especially of attributes which have AttributeHierachyEnabled set to True. Although SQL Server 2005 Analysis Services can support many attributes in a dimension, having more attributes than are actually used decreases performance unnecessarily and can make the end-user experience more difficult. </font></p>
<p><font size="1" face="Arial">It is usually not necessary to create an attribute for every column in a table. Even though the wizards do this by default in Analysis Services 2005, a better design approach is to start with the attributes you know you'll need, and later add more attributes.&#160; Adding attributes as you discover they are needed is generally better a better practice than adding everything and then removing attributes.</font></p>
<h6><font size="1">Do not create hierarchies where an attribute of a lower level contains fewer members than an attribute of the level above</font></h6>
<p><font size="1" face="Arial">A hierarchy such as this is frequently an indication that your levels are in the incorrect order: for example, [City] above [State]. It might also indicate that the key columns of the lower level are missing a column: for example, [Year] above [Quarter Number] instead of [Year] above [Quarter with Year].&#160; Either of these situations will lead to confusion for end-users trying to use and understand the cube.</font></p>
<h6><font size="1">Do not include more than one non-aggregatable attribute per dimension</font></h6>
<p><font size="1" face="Arial">Because there is no All member, each non-aggregatable attribute will always have some non-all member selected, even if not specified in a query.&#160; Therefore, if you include multiple non-aggregatable attributes in a dimension, the selected attributes will conflict and produce unexpected numbers.&#160; </font></p>
<p><font size="1" face="Arial">For example, in a time dimension it might not make sense to sum the members of [Calendar Year] or [Fiscal Year], but if both are made non-aggregatable, whenever a user asks for data for a specific [Calendar Year] it will be filtered by the default [Fiscal Year] unless they also specify the [Fiscal Year].&#160; Worse, because [Calendar Year] and [Fiscal Year] do not align but overlap, it is difficult to obtain the full data for either a [Calendar Year] or a [Fiscal Year] because the one is filtered by the other.</font></p>
<h6><font size="1">Do use key columns that completely and correctly define the uniqueness of the members in an attribute</font></h6>
<p><font size="1" face="Arial">Usually a single key column is sufficient, but sometimes multiple key columns are necessary to uniquely identify members of an attribute.&#160; For example, it is common in time dimensions to have a [Month] attribute include both [Year] and [Month Name] as key columns.&#160; This is known as a <em>composite key</em> and identifies January of 1997 as being a different member than January of 1998. When you use [Month] in a time hierarchy that also contains [Year], this distinction between January of 1997 and January of 1998 is important.&#160; </font></p>
<p><font size="1" face="Arial">It may also make sense to have a separate [Month of Year] attribute that has only [Month Name] as the key.&#160; This [Month of Year] attribute contains a single January member that spans all years, which can be useful for comparing seasonal data. However, this attribute should not be used in a hierarchy together with [Year] because there is no relationship between [Month of Year] and [Year].&#160; </font></p>
<p><font size="1" face="Arial">Similar distinctions between [Quarter] and [Quarter of Year], [Semester] and [Semester of Year], and so on should also be made by setting appropriate key columns.</font></p>
<h6><font size="1">Do perform Process Index after doing a Process Update if the dimension contains flexible AttributeRelationships or a parent-child hierarchy</font></h6>
<p><font size="1" face="Arial">An aggregation is considered flexible if any attribute included in the aggregation is related, either directly or indirectly, to the key of its dimension through an AttributeRelationship with RelationshipType set to Flexible.&#160; Aggregations that include parent-child hierarchies are also considered flexible. </font></p>
<p><font size="1" face="Arial">When a dimension is processed by using the Process Update option, any flexible aggregations that the dimension participates in might be dropped, depending on the contents of the new dimension data.&#160; These aggregations are not rebuilt by default, so Process Index must then be explicitly performed to rebuild them.</font></p>
<h6><font size="1">Do use numeric keys for attributes that contain many members (&gt;1 million)</font></h6>
<p><font size="1" face="Arial">Using a numeric key column instead of a string key column or a composite key will improve the performance of attributes that contain many members.&#160; This best practice is based on the same concept as using surrogate keys in relational tables for more efficient indexing.&#160; You can specify the numeric surrogate column as the key column and still use a string column as the name column so that the attribute members appear the same to end-users. As a guideline, if the attribute has more than one million members, you should consider using a numeric key.</font></p>
<h6><font size="1">Do not create redundant attribute relationships</font></h6>
<p><font size="1" face="Arial">Do not create attribute relationships that are transitively implied by other attribute relationships.&#160; The alternative paths created by these redundant attribute relationships can cause problems for the server and are of no benefit to the dimension.&#160; For example, if the relationships A-&gt;B, B-&gt;C, and A-&gt;C have been created, A-&gt;C is redundant and should be removed.</font></p>
<h6><font size="1">Do include the key columns of snowflake tables joined to nullable foreign keys as attributes that have NullProcessing set to UnknownMember</font></h6>
<p><font size="1" face="Arial">If tables that are used in a dimension are joined on a foreign key column that might contain nulls, it is important that you include in your design an attribute whose key column is the corresponding key in the lookup table. Without such an attribute, the OLAP server would have to issue a query to join the two tables during dimension processing.&#160; This makes processing slower; moreover, the default join that is created by the OLAP server would exclude any rows that contain nulls in the foreign key column.&#160; It is important to set the NullProcessing option on the key column of this attribute to UnknownMember.&#160; The reason is that, by default, nulls are converted to zeros or blanks when the engine processes attributes.&#160; This can be dangerous when you are processing a nullable foreign key. Conversion of a null to zero at best produces an error; in the worst case, the zero may be a legitimate value in the lookup table, thereby producing incorrect results. </font></p>
<p><font size="1" face="Arial">To handle nullable foreign keys correctly, you must also set UnknownMember to Visible on the dimension. The Cube Wizard and Dimension Wizard currently set this property automatically; however, the Dimension Wizard lets you manually de-select the key attribute of snowflake tables. You must not deselect the key column if the corresponding foreign key is nullable.</font></p>
<p><font size="1" face="Arial">If you do not want to browse the attribute that contains the lookup table key column, you can set AttributeHierarchyVisible to False.&#160; However, AttributeHierarchyEnabled must be set to True because it is necessary that all other attributes in the lookup table be directly or indirectly related to the lookup key attribute in order to avoid the automatic creation of new joins during dimension processing.</font></p>
<h6><font size="1">Do set the RelationshipType property appropriately on AttributeRelationships based on whether the relationships between individual members change over time</font></h6>
<p><font size="1" face="Arial">The relationships between members of some attributes, such as dates in a given month or the gender of a customer, are not expected to change.&#160; Other relationships, such as salespeople in a given region or the marital status of a customer, are more prone to change over time.&#160; You should set RelationshipType to Flexible for those relationships that are expected to change and set RelationshipType to Rigid for relationships that are not expected to change.</font></p>
<p><font size="1" face="Arial">When you set RelationshipType appropriately, the server can optimize the processing of changes and re-building of aggregations.</font></p>
<p><font size="1" face="Arial">By default, the user interface always sets RelationshipType to Flexible.</font></p>
<h6><font size="1">Avoid using ErrorConfigurations with KeyDuplicate set to IgnoreError on dimensions</font></h6>
<p><font size="1" face="Arial">When KeyDuplicate is set to IgnoreError, it can be difficult to detect problems with incorrect key columns, incorrectly defined AttributeRelationships, and data consistency issues.&#160; Instead of using the IgnoreError option, in most cases it is better to correct your design and clean the data.&#160; The IgnoreError option may be useful in prototypes where correctness is less of a concern. Be aware that the default value for KeyDuplicate is IgnoreError. Therefore, it is important to change this value after prototyping is complete to ensure data consistency.</font></p>
<h6><font size="1">Do define explicit default members for non-aggregatable attributes</font></h6>
<p><font size="1" face="Arial">By default, the All member is used as the default member for aggregatable attributes. This default works very well for aggregatable attributes, but non-aggregatable attributes have no obvious choice for the server to use as a default member, therefore a member will be selected arbitrarily. This arbitrarily selected member is then selected whenever the attribute is not explicitly included in an MDX query. To avoid this, it is important to explicitly set a default value for each non-aggregatable attribute.&#160; </font></p>
<p><font size="1" face="Arial">Default members can be explicitly set either on the DimensionAttribute or in the cube script.</font></p>
<h6><font size="1">Avoid creating user-defined hierarchies that do not have attribute relationships relating each level to the level above</font></h6>
<p><font size="1" face="Arial">Having attribute relationships between every level in a hierarchy makes the hierarchy strong and enables significant server optimizations.</font></p>
<h6><font size="1">Avoid creating diamond-shaped attribute relationships</font></h6>
<p><font size="1" face="Arial">A <em>Diamond-shaped relationship</em> refers to a chain of attribute relationships that splits and rejoins but contains no redundant relationships.&#160; For example, Day-&gt;Month-&gt;Year and Day-&gt;Quarter-&gt;Year have the same start and end points, but do not have any common relationships.&#160; The presence of multiple paths can create some ambiguity on the server.&#160; If preserving the multiple paths is important, it is strongly recommended that you resolve the ambiguity by creating user hierarchies that contain all the paths.</font></p>
<h6><font size="1">Consider setting AttributeHierarchyEnabled to False on attributes that have cardinality that closely matches the key attribute</font></h6>
<p><font size="1" face="Arial">When an attribute contains roughly one value for each distinct value of the key attribute, it usually means that the attribute contains only alternative identification information or secondary details.&#160; Such attributes are usually not interesting to pivot or group by.&#160; For example, the Social Security number or telephone number may be interesting properties to view, but there is very little value in being able to pivot and group based on SSN or telephone.&#160; Setting AttributeHierarchyEnabled to False on such attributes will reduce the complexity of the dimension for end-users and improve its performance.</font></p>
<p><font size="1" face="Arial">If you want to be able to browse such attributes, you can set AttributeHierarchyEnabled to True; however, you should consider setting AttributeHierarchyOptimized to NotOptimized and setting GroupingBehavior to DiscourageGrouping. By setting these properties, you can improve performance and indicate to the users that the attribute is not very useful for grouping.</font></p>
<h6><font size="1">Consider setting AttributeHierarchyVisible to False on the key attribute of parent-child dimensions</font></h6>
<p><font size="1" face="Arial">Because the members of the key attribute are also contained in the parent-child hierarchy in a more organized manner, it is usually unnecessary and confusing to the end-user to expose the flat list of members contained in the key attribute.</font></p>
<h6><font size="1">Avoid setting UnknownMember=Hidden</font></h6>
<p><font size="1" face="Arial">When you suppress unknown members, the effect is to hide relational integrity issues; moreover, because hidden members might contain data, results might appear not to add up. Therefore, we recommend that you avoid use of this setting except in prototype applications.</font></p>
<h6><font size="1">Do use MOLAP storage mode for dimensions with outline calculations (custom rollups, semi-additive measures, and unary operators)</font></h6>
<p><font size="1" face="Arial">Dimensions that contain custom rollups or unary operators will perform significantly better using MOLAP storage.&#160; The following dimension types will also benefit from using MOLAP storage: an Account dimension in a measure group that contains measures aggregated using ByAccount; the first time dimension in a measure group that contains other semi-additive measures.</font></p>
<h6><font size="1">Do use a 64 bit server if you have dimensions with more than 10 million members</font></h6>
<p><font size="1" face="Arial">If a dimension contains more than 10 million members, using an x64 or an IA-64-based server is recommended for better performance.</font></p>
<h6><font size="1">Do set the OrderBy property for time attributes and other attributes whose natural ordering is not alphabetical</font></h6>
<p><font size="1" face="Arial">By default, the server orders attribute members alphabetically, by name.&#160; This ordering is especially undesirable for time attributes.&#160; To obtain the desired ordering, use the OrderBy and OrderByAttributes properties and explicitly specify how you want the members ordered.&#160; For time-based attributes, there is frequently a date or numeric key column that can be used to obtain the correct chronological ordering.</font></p>
<h6><font size="1">Do expose a DateTime MemberValue for date attributes</font></h6>
<p><font size="1" face="Arial">Some clients, such as Excel, will take advantage of the MemberValue property of date members and use the DateTime value that is exposed. When Excel recognizes the value as DateTime, Excel can treat the value as a date type and apply date functions to the value, as well as provide better formatting and filtering.&#160; If the key column is a single DateTime column and the name column has not been set, this MemberValue is automatically derived from the key column and no action is necessary.&#160; However, in other cases, you can ensure that the MemberValue is DateTime by explicitly specifying the ValueColumn property of the attribute. </font></p>
<h6><font size="1">Do set AttributeHierarchyEnabled to False, specify a ValueColumn and specify the MimeType of the ValueColumn on attributes that contain images</font></h6>
<p><font size="1" face="Arial">Because there is no value in browsing the member names of an attribute that contains an image, you should disable browsing by setting AttributeHierarchyEnabled to False.&#160; To help clients recognize and display the member property of the attribute as an image, specify the ValueColumn property of the attribute and then set MimeType to an appropriate image type.</font></p>
<h6><font size="1">Avoid setting IsAggregatable to False on any attribute other than the parent attribute in a parent-child dimension</font></h6>
<p><font size="1" face="Arial">Non-aggregatable attributes have non-all default members. These default members affect the result of queries whenever the attributes are not explicitly included.&#160; Because parent-child hierarchies generally represent the most interesting exploration path in dimensions that contain them, it is best to avoid having non-aggregatable attributes other than the parent attribute.</font></p>
<h6><font size="1">Do set dimension and attribute Type properties correctly for Time, Account, and Geography dimensions</font></h6>
<p><font size="1" face="Arial">For time dimensions, it is important to set the dimension and attribute types correctly so that time-related MDX functions and the time intelligence of the Business Intelligence Wizard can work correctly.&#160; For Account dimensions, it is similarly important to set appropriate account types when using measures with the aggregate function ByAccount.&#160; Geography types are not used by the server, but provide information for client applications.</font></p>
<p><font size="1" face="Arial">A common mistake is to set the Type property on a dimension but not on an attribute, or vice-versa. Another common mistake when configuring time dimensions is to confuse the different time attribute types, such as [Month] and [Month of Year].</font></p>
<h6><font size="1">Consider creating user-defined hierarchies whenever you have a chain of related attributes in a dimension</font></h6>
<p><font size="1" face="Arial">Chains of related attributes usually represent an interesting navigation path for end-users, and defining hierarchies for these will also provide performance benefits.</font></p>
<h6><font size="1">Do include all desired attributes of a logical business entity in a single dimension instead of splitting them up over several dimensions</font></h6>
<p><font size="1" face="Arial">In Analysis Services 2000, each hierarchy was in reality a separate dimension and attributes such as gender and age would also be separate dimensions.&#160; In Analysis Services 2005, a dimension can and should contain the complete information about a logical business entity, including multiple hierarchies and many attributes.&#160; This does not mean that every piece of information available must be included in the dimension, but rather that any desired information should be included in one dimension instead of split over many dimensions.</font></p>
<p><font size="1" face="Arial">There are two exceptions to this guideline:</font></p>
<ol>
<li>
<p><font size="1" face="Arial">A dimension can only contain one parent-child hierarchy.</font></p>
</li>
<li>
<p><font size="1" face="Arial">To model multiple joins to a lookup table within a dimension's schema, you must create a separate dimension based on the lookup table and then use this as a referenced dimension.</font></p>
</li>
</ol>
<h6><font size="1">Do not combine unrelated business entities into a single dimension</font></h6>
<p><font size="1" face="Arial">Combining attributes of independent business entities, such as customer and product or warehouse and time, into a single dimension will not only create a confusing model, but also reduce query performance because auto-exist will be applied across attributes within the dimension.</font></p>
<p><font size="1" face="Arial">Another way to state this rule is that the values of the key attribute of a dimension should uniquely identify a single business entity and not a combination of entities.&#160; Generally this means having a single column key for the key attribute.</font></p>
<h6><font size="1">Do set NullProcessing to UnknownMember on each attribute that has nulls and is used to join to a referenced dimension</font></h6>
<p><font size="1" face="Arial">By default, nulls are converted to zeros or blanks when the engine processes attributes.&#160; This can be dangerous when processing a nullable foreign key, because if a null is converted to zero when zero is a legitimate value in the reference dimension, the join on the values can produce incorrect results. At best, conversion to zero will produce an error.</font></p>
<p><font size="1" face="Arial">To prevent these errors, you must also set UnknownMember to Visible on the referenced dimension.</font></p>
<p><font size="1" face="Arial">The Cube Wizard in SQL Server 2005 Analysis Services handles both settings automatically, except when dealing with existing dimensions where UnknownMember is not set to Visible.</font></p>
<h6><font size="1">Do set NullKeyConvertToUnknown to IgnoreError on the ErrorConfiguration on any measure groups that contain a dimension referenced through a nullable column</font></h6>
<p><font size="1" face="Arial">By default, nulls are converted to zeros or blanks when the engine processes granularity attributes.&#160; This can be dangerous when you are processing a nullable foreign key, because if a null value is converted to zero and zero is a legitimate value in the dimension, the join can produce incorrect results. At best, the conversion will produce errors.</font></p>
<p><font size="1" face="Arial">To prevent conversion of nulls, you must also set UnknownMember to Visible on the dimension.</font></p>
<p><font size="1" face="Arial">The Cube Wizard in SQL Server 2005 Analysis Services handles these settings automatically, except when dealing with existing dimensions where UnknownMember is not set to Visible.</font></p>
<h6><font size="1">Consider setting AttributeHierarchyVisible to False for attributes included in user-defined hierarchies</font></h6>
<p><font size="1" face="Arial">It is usually not necessary to expose an attribute in its own single level hierarchy when that attribute is included in a user-defined hierarchy.&#160; This duplication only complicates the end-user experience without providing additional value.&#160; </font></p>
<p><font size="1" face="Arial">One common case in which it is appropriate to present two views of an attribute is in time dimensions.&#160; The ability to browse by [Month] and the ability to browse by [Month-Quarter-Year] are both very valuable. However, these two month attributes are actually separate attributes.&#160; The first contains only the month value such as “January” while the second contains the month and the year such as “January 1998”.</font></p>
<h6><font size="1">Do not use proactive caching settings that put dimensions into ROLAP mode</font></h6>
<p><font size="1" face="Arial">For performance reasons, we strongly discourage the use of dimension proactive caching settings that may put the dimension in ROLAP mode.&#160; To ensure that a dimension with proactive caching enabled will never enter ROLAP mode, you should set the OnlineMode property to OnCacheComplete.&#160; You can also prevent use of ROLAP mode by deselecting the Bring online immediately check box in the Storage Options dialog box.</font></p>
<h6><font size="1">Avoid making an attribute non-aggregatable unless it is at the end of the longest chain of attribute relationships in the dimension</font></h6>
<p><font size="1" face="Arial">Non-aggregatable attributes have non-all default members that affect the result of queries in which values for those attributes are not explicitly specified.&#160; Therefore, you should avoid making an attribute non-aggregatable unless that attribute is regularly used.&#160; Because the longest chain of attributes generally represents the most interesting exploration path for users, it is best to avoid having non-aggregatable attributes in other, less interesting chains.</font></p>
<h6><font size="1">Consider creating at least one user-defined hierarchy in each dimension that does not contain a parent-child hierarchy</font></h6>
<p><font size="1" face="Arial">Most (but not all) dimensions contain some hierarchical structure to the data which is worth exposing in the cube.&#160; Frequently the Cube Wizard or Dimension Wizard will not detect this hierarchy. In these cases, you should define a hierarchy manually.</font></p>
<h6><font size="1">Do set the InstanceSelection property on attributes to help clients determine the best way to display attributes for member selection</font></h6>
<p><font size="1" face="Arial">If there are too many members to display in a single list, the client user interface can use other methods, such as filtered lists, to display the members. By setting the InstanceSelection property, you provide a hint to client applications to suggest how a list of items should be displayed, based on the expected number of items in the list.</font></p>
<p><font size="1" face="Arial">Recommended guidelines for setting this property are as follows: </font></p>
<p><font size="1" face="Arial">Property Value </font></p>
<p><font size="1" face="Arial">Description </font></p>
<p><font size="1" face="Arial">Guidelines</font></p>
<p><font size="1" face="Arial">None</font></p>
<p><font size="1" face="Arial">Do not display a selection list. Enable users to enter values directly.</font></p>
<p><font size="1" face="Arial">DropDown</font></p>
<p><font size="1" face="Arial">The number of items is small enough to display in a drop-down list.</font></p>
<p><font size="1" face="Arial">&lt;100 members</font></p>
<p><font size="1" face="Arial">List</font></p>
<p><font size="1" face="Arial">The number of items is too large for a drop-down list but does not require filtering.</font></p>
<p><font size="1" face="Arial">&lt; 500 members</font></p>
<p><font size="1" face="Arial">FilteredList</font></p>
<p><font size="1" face="Arial">The number of items is large enough to require users to filter the items to be displayed.</font></p>
<p><font size="1" face="Arial">&lt; 5000 members</font></p>
<p><font size="1" face="Arial">MandatoryFilter</font></p>
<p><font size="1" face="Arial">The number of items is so large that the display must always be filtered. </font></p>
<p><font size="1" face="Arial">&gt; 5000 members</font></p>
<p><font size="1" face="Arial">The following C# code sample shows how to set the property dynamically:</font></p>
<pre><font size="1" face="Arial">if ( estimatedCount &lt; 100 )&#160;&#160;&#160;&#160; attribute.InstanceSelection = InstanceSelection.DropDown;
else if ( estimatedCount&lt; 500 )&#160;&#160;&#160;&#160; attribute.InstanceSelection = InstanceSelection.List;
else if ( estimatedCount&lt; 5000 )&#160;&#160;&#160;&#160; attribute.InstanceSelection = InstanceSelection.FilteredList;
else&#160;&#160;&#160;&#160; attribute.InstanceSelection = InstanceSelection.MandatoryFilter;</font></pre>
<p><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"></a><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"><font size="1" face="Arial">Top Of Page</font></a></p>
<h5><font size="1">Cube Design Best Practices</font></h5>
<p><font size="1" face="Arial">Well-designed cubes will better match the needs of your end-users. The following best practices can improve usability and also performance of the cube.</font></p>
<h6><font size="1">Avoid including unrelated measure groups in the same cube</font></h6>
<p><font size="1" face="Arial">Having many measure groups in a cube can adversely affect the query performance of the cube, even for queries that only use a single measure group.&#160; If your DSV contains many potential fact tables and they will not usually be used together, consider creating multiple smaller cubes containing topic areas that are used together.&#160; Then, you can enable occasional cross-topic querying by creating linked measure groups that join together all measure groups in a special cross-topic cube.</font></p>
<h6><font size="1">Avoid having too many parent-child dimensions in a cube, especially when the dimension contains custom rollups or unary operators</font></h6>
<p><font size="1" face="Arial">Parent-child dimensions, especially those that contain custom rollups and unary operators, are very powerful and flexible.&#160; However, in order to prevent poor query performance, such parent-child dimensions should only be used as necessary.</font></p>
<h6><font size="1">Do set AttributeHierarchyEnabled to False on any cube attributes that are below the level of granularity of all measure groups in the cube</font></h6>
<p><font size="1" face="Arial">Attributes are considered below the level of granularity for a measure group when no chain of attribute relationships exists between the granularity attribute and the attribute in question.&#160; Such attributes will never have any data associated with them in the cube and will only confuse end-users.&#160; For example, if a time dimension contains day, week, month and year attributes, whereas an inventory cube contains only data updated on a weekly basis, it is best to disable the day attribute for this cube by setting AttributeHierarchyEnabled to False for the day attribute only. </font></p>
<h6><font size="1">Avoid having very big intermediate measure groups or dimensions of many-to-many dimensions</font></h6>
<p><font size="1" face="Arial">Having very big intermediate measure groups could lead to potential performance issues in many-many dimensions. “Very big” means larger than the measure group or more than one million rows. You can also experience performance issues when using very big dimensions in many-many dimension relationships.</font></p>
<h6><font size="1">Consider using a processing query when using the scheduled polling option of proactive caching</font></h6>
<p><font size="1" face="Arial">A polling query is typically a singleton query that returns a value Analysis Services can use to determine whether changes have been made to a table or other relational object.&#160; The polling query tells the proactive caching mechanism when it must read in new data.&#160; </font></p>
<p><font size="1" face="Arial">In contrast, a processing query is a query that returns a rowset that contains the changes made to a table associated with an Analysis Services object since the last time the table was polled, in order to incrementally update the multidimensional OLAP (MOLAP) cache for the object. Therefore, the processing query tells the proactive caching mechanism what data is new.&#160; By setting the processing query, you can configure the system to read and process only the new data, instead of re-reading and re-processing the whole table.</font></p>
<h6><font size="1">Avoid creating multiple measure groups that have the same dimensionality and granularity </font></h6>
<p><font size="1" face="Arial">Having too many measure groups can adversely affect performance.&#160; Moreover, the presence of many similar measure groups presents a more complex model to the end-user by dividing data on a common subject.&#160; Instead, you should consider creating a single measure group that contains multiple partitions.&#160; The common exception to this guideline is distinct count measures, which for performance reasons should be in their own measure groups.</font></p>
<h6><font size="1">Do put each distinct count measure into a separate measure group</font></h6>
<p><font size="1" face="Arial">Put each distinct count measure into its own measure group. This will improve performance.</font></p>
<h6><font size="1">Do set any explicit default members of role-playing dimensions directly on the cube dimensions</font></h6>
<p><font size="1" face="Arial">A dimension that has been given a different name in a cube than it has outside the cube is said to be role-playing.&#160; The name that is used in the cube is known as the role the dimension plays within that cube.&#160; Role-playing is used most often when a dimension plays more than one role in a cube.&#160; For example, the [Order Date] and [Ship Date] cube dimensions are both based on the [Date] dimension, but are assigned different names, or roles.</font></p>
<p><font size="1" face="Arial">Because such a dimension has a different name in the cube, whereas the default member expression is evaluated in the context of the cube, any explicit reference to the original dimension name in the default member will be invalid.&#160; To specify the default member on the cube dimension, you can use the following syntax in the cube’s calculation script: </font></p>
<pre><font size="1" face="Arial">ALTER CUBE CurrentCube UPDATE DIMENSION &lt;dimension name&gt;, DEFAULT_MEMBER='&lt;default member&gt;'</font></pre>
<p><font size="1" face="Arial">This has the added benefit of enabling different default members for each of the roles a dimension plays in a cube. Such role specific default members frequently make sense from the business perspective.</font></p>
<h6><font size="1">Do reuse dimensions multiple times in a cube instead of creating duplicates of a dimension</font></h6>
<p><font size="1" face="Arial">In Analysis Services 2000, it was necessary to create new copies of a dimension for role-playing. In other words, to use two identical date dimensions, [Ship Date] and [Order Date], you needed to have two separate dimensions.&#160; However, in Analysis Services 2005, this is not necessary and should be avoided as it will introduce unnecessary storage and maintenance costs.</font></p>
<h6><font size="1">Avoid having cubes with a single dimension</font></h6>
<p><font size="1" face="Arial">If a cube has only one dimension, you should consider splitting this single dimension into multiple dimensions based on logical business entities.&#160; Typically, a cube contains only a single dimension because it was based on a single de-normalized table, which the Cube Wizard was unable to break into multiple dimensions.&#160; </font></p>
<p><font size="1" face="Arial">This single dimension almost always contains multiple logical business entities. From the perspective of the user, the different business entities would be more cleanly modeled and navigated as separate dimensions.</font></p>
<h6><font size="1">Do use the smallest numeric data type possible for measures</font></h6>
<p><font size="1" face="Arial">The data type of measures must be large enough to hold the largest aggregated value (the &quot;all&quot; value) but should be no larger than necessary to reduce storage costs.</font></p>
<h6><font size="1">Do ensure that the Collation property of OLAP objects is consistent with the collation of the relational source data when dealing with multilingual data</font></h6>
<p><font size="1" face="Arial">Collation controls both the sorting and equivalence of strings; therefore it is important to have the Analysis Services server use the appropriate collation for the data. If you use the wrong collation, you might see strange results, especially if the column is used for a distinct count measure.&#160; </font></p>
<p><font size="1" face="Arial">Collations can be set at the level of the server, database, cube, and dimension and also on individual column bindings.&#160; The important point is to have the collation of your OLAP objects be consistent with the collation of the relational data on which they are built.&#160; For example, the caption columns of translations usually contain text in another language and are therefore likely to have a different collation.</font></p>
<h6><font size="1">Do materialize referenced dimensions</font></h6>
<p><font size="1" face="Arial">To improve performance, reference dimensions should be materialized.&#160; The only exception to this is the rare case when you are creating a reference dimension relationship between a local dimension and a linked measure group.&#160; When a reference dimension is created by using the user interface for SQL Server 2005 Analysis Services, it will be materialized by default.&#160; </font></p>
<h6><font size="1">Avoid using linked dimensions, especially if your cube has outline calculations (custom rollups, semi-additive measures, or unary operators) or scripts</font></h6>
<p><font size="1" face="Arial">Although it is possible to use dimensions linked from another database (or server) with a local measure group, this will adversely affect performance and should be avoided when possible. Instead, consider creating a local copy of the dimension. Even on the same server,&#160;&#160; you should avoid linked dimensions.</font></p>
<p><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"></a><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"><font size="1" face="Arial">Top Of Page</font></a></p>
<h5><font size="1">Partition Design Best Practices</font></h5>
<p><font size="1" face="Arial">Following some simple best practices can help ensure an effective data storage strategy that will enable the OLAP server to scale efficiently to your data volumes.</font></p>
<h6><font size="1">Avoid having partitions with more than 20 million rows</font></h6>
<p><font size="1" face="Arial">Large partitions should generally be broken up into multiple smaller partitions for better performance. As a rule, no partition should have more than 20 million rows.</font></p>
<h6><font size="1">Avoid having many small partitions in a measure group</font></h6>
<p><font size="1" face="Arial">Small partitions should generally be combined into fewer, larger partitions for better performance. As a guideline, consider combining partitions when a measure group has more than five partitions with less than two million rows each.</font></p>
<h6><font size="1">Do set the Slice property on partitions that are ROLAP or partitions that use proactive caching</font></h6>
<p><font size="1" face="Arial">Use of the Slice property lets the server know which partitions it must look in for data to answer queries.&#160; For example, if a partition contains a slice that states it contains only data for 2002, when a query requests sales in 2003, the server will know it does not have to look in that partition in order to answer that query.</font></p>
<p><font size="1" face="Arial">For MOLAP partitions, you do not have to specify the slice because the server will be able to figure out the relevant partitions after the data has been processed.&#160; However, when you use proactive caching, it’s a good idea to specify the slice manually since the partition may be treated as ROLAP during the construction of the MOLAP cache.&#160; (If a slice is manually specified on a MOLAP partition and that slice is not consistent with the data that is contained in the partition, the server will raise an error during processing of the data.)&#160; </font></p>
<p><font size="1" face="Arial">For ROLAP partitions, a slice should be specified or the partition will always have to be queried.&#160; </font></p>
<p><font size="1" face="Arial">To set the Slice property in Business Intelligence Development Studio, select the partition in the Partitions tab of the Cube Editor. In the Properties window, click the text box for the Slice property.&#160; Click the ellipsis (...) button to open the Partition Slice dialog box. You can type an MDX expression to specify the member on which you want to slice.&#160; To slice on multiple hierarchies, enter a tuple containing the members on which you want to slice.</font></p>
<h6><font size="1">Consider partitioning a distinct count measure group along the dimension used most often to query the distinct count measure</font></h6>
<p><font size="1" face="Arial">When partitioning a measure group that includes a distinct count measure, consider partitioning the measure group along the dimension that is most often used to query distinct count measure. This will provide improved query performance by reducing the frequency that all partitions must be accessed.</font></p>
<p><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"></a><a href="http://technet.microsoft.com/zh-cn/library/cc966399%28en-us%29.aspx#mainSection"><font size="1" face="Arial">Top Of Page</font></a></p>
<h5><font size="1">Aggregation Design Best Practices</font></h5>
<p><font size="1" face="Arial">Good aggregation design is important for achieving good performance when dealing with large amounts of data. Although aggregation design is a complex topic, much of the complexity can be handled automatically by the Storage Design Wizard in SQL Server 2005 Analysis Services.&#160; If you decide to manually design aggregations using some other tool, you’ll need to plan your design much more carefully.&#160; The following best practices contain guidance to help succeed in both scenarios.</font></p>
<h6><font size="1">Consider having aggregations for each partition of significant size</font></h6>
<p><font size="1" face="Arial">Aggregations will generally improve the performance for partitions of non-trivial size. We recommend using aggregations when partition size exceeds 500,000 rows.</font></p>
<h6><font size="1">Do include the granularity attribute of the time dimension in aggregations for measure groups with semi-additive measures</font></h6>
<p><font size="1" face="Arial">Semi-additive measures are calculated at run time by using the granularity attribute of the time dimension.&#160; Therefore, only aggregations that contain this granularity attribute will help performance when calculating the value of semi-additive measures.&#160; </font></p>
<p><font size="1" face="Arial">If you set the AggregationUsage property to Full, the Aggregation Design Wizard and the Usage-Based Optimization Wizard will include this attribute in every aggregation.&#160; If you manually design your aggregations, make sure to include such attributes in every aggregation.</font></p>
<h6><font size="1">Do not build too many aggregations</font></h6>
<p><font size="1" face="Arial">Do not build excessive aggregations. This can adversely affect performance by of increasing search space during queries and increasing the work necessary during processing.&#160; As a rule of thumb, do not build more than 500 aggregations per partition.</font></p>
<h6><font size="1">Consider sharing aggregation designs between partitions of similar size and usage</font></h6>
<p><font size="1" face="Arial">It is usually not necessary or desirable from a management perspective to create separate aggregation designs for every partition.&#160; You generally only need different aggregation designs for partitions that have different sizes or usage patterns. Therefore, similar aggregation designs are not necessary and will add complexity to the database.&#160; </font></p>
<p><font size="1" face="Arial">Partitions that have similar size and usage should share the same aggregation designs. As a rule, three aggregation designs per measure group are generally enough.</font></p>
<h6><font size="1">Consider creating separate aggregation designs for partitions with significantly different size or usage</font></h6>
<p><font size="1" face="Arial">When partitions have significantly different size or usage patterns, it is generally better to create separate aggregation designs and customize the design appropriately.&#160; For example, it makes sense to create separate partitions for each month of the current year and use the same aggregation design for these partitions. However, you will probably want to create a separate aggregation design for the partition that contains all the data for a past year.&#160; This is better because archived data usually is combined into larger partitions and is accessed less frequently.</font></p>
<p><font size="1" face="Arial">For example, the storage settings for partitions can be managed by using the following guidelines:</font></p>
<p><font size="1" face="Arial">&#160;&#160; Frequently queried partitions -&gt; Use MOLAP with lots of aggregations</font></p>
<p><font size="1" face="Arial">&#160;&#160; Periodically queried partitions -&gt; Use MOLAP with less or no aggregations</font></p>
<p><font size="1" face="Arial">&#160;&#160; Rarely queried partitions -&gt; Use ROLAP with no aggregations</font></p>
<h6><font size="1">Do use a lower performance gain with regular aggregation design and a higher performance gain with usage-based optimization</font></h6>
<p><font size="1" face="Arial">When you design generic aggregations, you should target a lower performance gain (20-30%).&#160; When you design aggregations using the Usage-Based Optimization Wizard, you should target a higher performance gain (70-80%), because these aggregations are more specific to actual use.</font></p>
<h6><font size="1">Consider setting AggregationUsage to Unrestricted on high-use attributes that are not the key of a dimension and not in a hierarchy</font></h6>
<p><font size="1" face="Arial">By default, the aggregation design algorithm considers only key attributes and attributes in natural hierarchies for inclusion in aggregations.&#160; Although this is usually the best strategy, if you have an attribute that is neither the key attribute nor contained in a hierarchy, but you expect people to group by the attribute or filter on it, you should consider setting AggregationUsage to Unrestricted. When you do this, the aggregation design algorithm will consider the attribute when it designs aggregations.</font></p>
<h6><font size="1">Avoid Setting AggregationUsage to Full on Large Attributes</font></h6>
<p><font size="1" face="Arial">Avoid setting the AggregationUsage property to Full on attributes that have many members. If you use the Aggregation Wizard, this setting may prevent any aggregations from being created, because this setting prevents the wizard from creating aggregations that do not include this attribute. </font></p>
<h6><font size="1">Do set member and row counts accurately for the partition when designing aggregations</font></h6>
<p><font size="1" face="Arial">Although member and row counts do not have to be exact, they should be reasonably accurate because they will be used to evaluate the cost, both in disk size and read time, of aggregations. Moreover, these counts will significantly affect the aggregations chosen by the aggregation design algorithm.&#160; </font></p>
<p><font size="1" face="Arial">You may find that not all members of a dimension exist in a partition, especially when the partition policy is based on the dimension: for example, in time-based partitioning.&#160; When this is true, it is important to provide an accurate approximation of the actual count of members found in the partition.</font></p>
<h6><font size="1">Consider including the granularity attribute of the intermediate dimensions of many-to-many dimensions in aggregations</font></h6>
<p><font size="1" face="Arial">When accessing data using a many-to-many dimension, the server will always use the granularity attribute of the dimension that serves as an intermediate dimension for that many-to-many dimension.&#160; Therefore, only aggregations that contain this granularity attribute will help performance when using many-to-many dimensions.&#160; Aggregations on other attributes of the intermediate dimension can still be useful when the intermediate dimension is used directly, and when the many-to-many dimension is not used in a query.</font></p>
<p><font size="1" face="Arial">If you have multiple dimensions shared between the measure groups in a many-to-many relationship, it is undefined which dimension the server will use as the intermediate dimension. Therefore, you should consider including the granularity attributes of each such potential intermediate dimension in aggregations.</font></p>
<h6><font size="1">Do include in aggregations the granularity attribute of dimensions that contain unary operators or custom rollups </font></h6>
<p><font size="1" face="Arial">Unary operators and custom rollups are calculated at run time from the granularity attribute of the dimension that contains them.&#160; Therefore, only aggregations that contain this granularity attribute will help performance when using dimensions with unary operators or custom rollups.&#160; </font></p>
<p><font size="1" face="Arial">The Aggregation Design Wizard and the Usage-Based Optimization Wizard will automatically include such dimension’s granularity attributes in aggregations.&#160; However, if you manually design aggregations, be sure to include such granularity attributes in every aggregation.</font></p>
<h6><font size="1">Avoid creating aggregations that are larger than one-third the size of the fact data</font></h6>
<p><font size="1" face="Arial">Aggregations this large generally do not help performance.&#160; The Aggregation Design Wizard and Usage-Based Optimization Wizard will apply this rule automatically, but you should monitor the size of aggregations and the size of the fact data when you manually design aggregations.</font></p>
<h6><font size="1">Do remove aggregation designs that are not applied to any partitions</font></h6>
<p><font size="1" face="Arial">Remove any aggregation designs that are not used by any partitions. These can slow metadata operations and offer no benefit.&#160; Removal of unused aggregations is performed automatically when you use the Copy Aggregation Design dialog box in SQL Server Management Studio. Removal of unused aggregations is also automatic in the Aggregation Design Wizard and the Usage-Based Optimization Wizard. However, if you manually create aggregation designs you should review the design when you have finished and remove unnecessary aggregations.</font></p>
<h6><font size="1">Do not create aggregations that contain multiple attributes from the same attribute relationship chain</font></h6>
<p><font size="1" face="Arial">It is redundant to include an attribute in an aggregation if the value of the attribute is implied by an attribute already in the aggregation, because the implied attribute’s value can be calculated from the first attribute.&#160; Also, for a given query, only one of these attributes is of interest in the aggregation.&#160; The best practice is to remove the implied attribute from the aggregation and, optionally, create a new aggregation that contains the implied attribute but not the implying attribute.&#160; The Aggregation Design Wizard and Usage-Based Optimization Wizard will apply this rule automatically, but if you manually design aggregations, you may have to modify your design to remove redundant attributes.</font></p>
<h6><font size="1">Consider including in aggregations only those attributes with rigid relationships to their dimension keys</font></h6>
<p><font size="1"></font><font face="Arial">Aggregations are considered flexible when any attribute included in the aggregation is related, either directly or indirectly, to the key of its dimension through any attribute relationship that has RelationshipType set to Flexible.&#160; Aggregations are also considered flexible when they include a parent-child hierarchy.</font>&#160; Because a flexible aggregation might be dropped during a Process Update of a dimension and will only be recreated when Process Index is performed, a better practice is to create rigid aggregations whenever possible, instead of flexible aggregations.&#160; Sometimes you can achieve this by selecting an attribute closer to the key of the dimension.</p>
<p><font size="1">For example, assume the following chain of relationships, where the notation ==&gt; means a rigid relationship and --&gt; means a flexible relationship:</font></p>
<p><font size="1">&#160;&#160;&#160; Customer ==&gt; City --&gt; Sales Region ==&gt; Country</font></p>
<p><font size="1">Given these relationships, any aggregations that use Sales Region or Country will be flexible, whereas aggregations that use Customer or City may be rigid.&#160; To avoid creating a flexible relationship, you might include City in the aggregation instead of Sales Region.</font></p>

	标签：<a href="http://www.imkevinyang.com/categories/techarticles/businessintelligence" title="BI/数据库" rel="tag">BI/数据库</a>, <a href="http://www.imkevinyang.com/tags/olap" title="OLAP" rel="tag">OLAP</a>, <a href="http://www.imkevinyang.com/tags/%e5%a4%9a%e7%bb%b4%e6%95%b0%e6%8d%ae%e9%9b%86" title="多维数据集" rel="tag">多维数据集</a>, <a href="http://www.imkevinyang.com/tags/%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96" title="性能优化" rel="tag">性能优化</a>, <a href="http://www.imkevinyang.com/tags/%e6%80%a7%e8%83%bd%e6%8c%87%e5%8d%97" title="性能指南" rel="tag">性能指南</a>, <a href="http://www.imkevinyang.com/tags/%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5" title="最佳实践" rel="tag">最佳实践</a>, <a href="http://www.imkevinyang.com/tags/%e7%bb%b4%e5%ba%a6%e8%ae%be%e8%ae%a1" title="维度设计" rel="tag">维度设计</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/04/analysis-services-2005-olap%e8%ae%be%e8%ae%a1%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5.html" title="Analysis Services 2005 OLAP设计最佳实践 (2009/04/02)">Analysis Services 2005 OLAP设计最佳实践</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/04/analysis-services%ef%bc%9a%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e5%a4%9a%e5%af%b9%e5%a4%9a%e7%bb%b4%e5%ba%a6%e5%90%97%ef%bc%9f.html" title="Analysis Services：你应该使用多对多维度吗？ (2010/04/12)">Analysis Services：你应该使用多对多维度吗？</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/bids%e9%83%a8%e7%bd%b2%e6%97%b6%e5%87%ba%e7%8e%b0%e5%85%83%e6%95%b0%e6%8d%ae%e7%ae%a1%e7%90%86%e5%99%a8%e5%8f%91%e7%94%9f%e9%94%99%e8%af%af.html" title="BIDS部署时出现元数据管理器发生错误 (2009/03/13)">BIDS部署时出现元数据管理器发生错误</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/08/olap%e4%b8%ad%e7%9a%84averageofchildren%e8%81%9a%e5%90%88%e6%96%b9%e5%bc%8f.html" title="OLAP中的AverageOfChildren聚合方式 (2009/08/10)">OLAP中的AverageOfChildren聚合方式</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/05/analysis-service-2005-olap-best-practice-white-paper.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: www.imkevinyang.com @ 2012-02-09 10:30:31 -->
