<?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; Key not found</title>
	<atom:link href="http://www.imkevinyang.com/tags/key-not-found/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/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</link>
		<comments>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#comments</comments>
		<pubDate>Fri, 09 Oct 2009 13:48:52 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[BI/数据库]]></category>
		<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Key not found]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[全半角]]></category>
		<category><![CDATA[处理异常]]></category>
		<category><![CDATA[属性未找到]]></category>
		<category><![CDATA[排序规则]]></category>
		<category><![CDATA[空格]]></category>

		<guid isPermaLink="false">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</guid>
		<description><![CDATA[问题描述
<p>某维度表的字符串列同时出现两条记录，A记录以半角空格（英文空格）结束，B记录以全角空格（中文空格）结束，除此之外其他部分均相同。Analysis Service处理的时候抛出“Key not found”的异常，导致处理失败。</p>
<p>为了实验，我们创建两张非常简单的表：</p>
<pre class="csharpcode"><span class="rem">-- 员工交易事实表</span>
<span class="kwrd">Create</span> <span class="kwrd">Tab&#8230;</span></pre>]]></description>
			<content:encoded><![CDATA[<h2>问题描述</h2>
<p>某维度表的字符串列同时出现两条记录，A记录以半角空格（英文空格）结束，B记录以全角空格（中文空格）结束，除此之外其他部分均相同。Analysis Service处理的时候抛出“Key not found”的异常，导致处理失败。</p>
<p>为了实验，我们创建两张非常简单的表：</p>
<pre class="csharpcode"><span class="rem">-- 员工交易事实表</span>
<span class="kwrd">Create</span> <span class="kwrd">Table</span> [FactTransaction](
    [TransactionKey] [<span class="kwrd">int</span>] <span class="kwrd">not</span> <span class="kwrd">null</span>,
    [EmployeeKey] [<span class="kwrd">int</span>] <span class="kwrd">not</span> <span class="kwrd">null</span>
)
<span class="rem">-- 员工维度表</span>
<span class="kwrd">Create</span> <span class="kwrd">Table</span> [DimEmployee](
    [EmployeeKey] [<span class="kwrd">int</span>]<span class="kwrd">not</span> <span class="kwrd">null</span>,
    [EmployeeName] [nvarchar](32) <span class="kwrd">not</span> <span class="kwrd">null</span>
)</pre>
<p>接着我们开始往维度表中添加几条记录。</p>
<pre class="csharpcode">insert <span class="kwrd">into</span> DimEmployee(EmployeeKey,EmployeeName)<span class="kwrd">values</span>(1,<span class="str">'员工 '</span>)    <span class="rem">-- 半角空格</span>
insert <span class="kwrd">into</span> DimEmployee(EmployeeKey,EmployeeName)<span class="kwrd">values</span>(2,<span class="str">'员工　'</span>)    -- 全角空格</pre>
<p>然后我们在BIDS中新建一个Analysis Service的Olap工程，将DimEmployee表作为维度表，并新建指标TotalTransactions ::= Count(TransactionKey)表示每个员工的交易数量：</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/10/image_thumb8.png" border="0" alt="image" width="129" height="58" /></p>
<p>所有设置保持默认，OK，现在开始处理Employee维度。这个时候Analysis Service会提示你：</p>
<blockquote><p>Processing Dimension Attribute 'EmployeeKey' failed. 1 rows have been read.</p>
<p>OLAP 存储引擎中存在错误: 处理时找不到以下属性键: 表:“dbo_DimEmployee”，列:“EmployeeName”，值:“员工 ”。该属性为“EmployeeName”。</p></blockquote>
<p>这个错误翻译成英文就是Key not found.</p>
<p><img style="display: inline; border-width: 0px;" title="处理时找不到以下属性键(Key not found)" src="http://www.imkevinyang.com/wp-content/uploads/2009/10/image_thumb9.png" border="0" alt="处理时找不到以下属性键(Key not found)" width="410" height="124" /></p>
<h2>问题分析</h2>
<h3>发生了什么事</h3>
<p>在我们上面设计的OLAP方案中，一个EmployeeKey有且只能有一个EmployeeName，EmployeeKey属性的处理依赖于EmployeeName属性。这个依赖关系在维度设计视图中的Attribute Relationship属性关系面板中指定。</p>
<p><img style="display: inline; border-width: 0px;" title="Attribute Relationship" src="http://www.imkevinyang.com/wp-content/uploads/2009/10/image_thumb10.png" border="0" alt="Attribute Relationship" width="244" height="124" /></p>
<p>Analysis Service会在处理完EmployeeName属性之后再处理EmployeeKey属性。在处理每一个EmployeeKey属性成员的时候，都会去找对应的EmployeeName属性成员。</p>
<p>上面的处理错误实际上就是说，在处理EmployeeKey的某个成员的时候，它对应的EmployeeName属性成员应该是“员工 ”（全角空格）的——从表记录中可以看到这个对应关系——但是在属性存储文件（Analysis Service自己的存储结构）中却找不到该属性成员。</p>
<p>这里没有告诉我们到底是哪个EmployeeKey属性成员处理的时候出了问题，但是由于我们的数据仓库非常简单，我们可以直接看出来，EmployeeName=“员工 ”（全角空格）的EmployeeKey为2。</p>
<p>那为什么全角空格的EmployeeName属性成员没有导入到Analysis Service的属性存储文件中呢？我们来展开看一下处理EmployeeName时Analysis Service向Sql Server发起的查询。</p>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  <span class="kwrd">DISTINCT</span>
 [dbo_DimEmployee].[EmployeeName] <span class="kwrd">AS</span> [dbo_DimEmployeeEmployeeName0_0]
  <span class="kwrd">FROM</span> [dbo].[DimEmployee] <span class="kwrd">AS</span> [dbo_DimEmployee]</pre>
<p>将这行代码放到Sql Server中去执行一下，<strong><span style="color: #008000;">我们发现sql Server只给我们返回了半角空格的记录，全角空格的记录被过滤掉了。这也就解释了，为什么全角空格的属性成员没能进入Analysis service中。进而导致依赖这个成员的属性处理失败</span></strong>。</p>
<h3>Sql Server Collation</h3>
<p>这里需要提一下Sql Server的排序规则（Collation）。排序规则会<img style="margin: 5px 0px 0px 5px; display: inline; border-width: 0px;" title="Sql Server Collation" src="http://www.imkevinyang.com/wp-content/uploads/2009/10/image_thumb11.png" border="0" alt="Sql Server Collation" width="244" height="189" align="right" />影响数据之间的比较以及顺序。具体细节参见MSDN：<a title="SQL Server Collation Fundamentals" href="Fundamentalshttp://msdn.microsoft.com/en-us/library/aa174903%28SQL.80%29.aspx" target="_blank">SQL Server Collation Fundamentals</a> 。这里我只提一个和这个问题相关的，并且容易被人遗忘的设置，那就是Width-Sensitive（宽度敏感）设置。我们知道，有些字符既有单字节形式（半角字符），又有双字节形式（全角字符），例如1234和１２３４。如果设置为宽度不敏感，那么Sql Server就会将这些字符的单双字节形式一视同仁。这样你在select distinct的时候，单双字节字符形式的字符串就只能一个。这也就是为什么上面我们select distinct的时候只出来半角空格的缘故。</p>
<h3>Sql Server和Analysis Service排序规则相同为什么还会出错？</h3>
<p>Analysis Service自己也有一个排序规则的设置。我们检查了一下这两者的设置，发现是一样的。那么Analysis Service在查找“员工 ”（全角空格）属性成员的时候，即使找不到这个成员，但是应该至少可以匹配到“员工 ”（半角空格）的成员才是呀。<strong><span style="color: #008000;">关键是，半角空格的成员也根本不存在。默认情况下，所有字符串类型的维度属性在处理时都会被right trim，也就是结尾的空格均会被去除。</span></strong></p>
<p><img style="display: inline; border-width: 0px;" title="维度属性面板Trimming" src="http://www.imkevinyang.com/wp-content/uploads/2009/10/image_thumb12.png" border="0" alt="维度属性面板Trimming" width="244" height="192" /></p>
<p>也就是说，最终进入Analysis Service的属性成员是“员工”，不带任何空格，而这个成员和全角空格（<strong><span style="color: #008000;">全角空格无法被right trimming掉</span></strong>）的显然无法匹配上。</p>
<h3>发散一下</h3>
<p>如果Analysis设置了对每个属性成员左右都trim的话，那么一旦数据仓库出现“ 员工”（左边带全角空格）和“ 员工”（左边带半角空格）的数据的时候，处理失败。</p>
<p>如果数据仓库中同时出现“员工”，“员工 ”（全角空格），那么也会造成出错，这是因为select distinct会将右侧空格去除之后再比较数据是否相等。</p>
<p>如果将维度属性的Trimming设置为None的话，那么当数据仓库中出现“员工”，“员工   ”（若干个半角空格结尾）这样数据的时候，也会造成处理失败，这也是为什么Analysis Service默认设置为right trimming的其中一个原因（和Sql Server的行为保持一致）。</p>
<p>如果数据中同时出现“员工 ”（半角空格），“员工 ”（全角空格），“员工 ”（先全角空格，再tab空格）这样的数据组合，处理正常。</p>
<h2>总结</h2>
<p>出现这样的情况，不好通过改变Sql Server或者Analysis Service的排序规则来修正这个问题。只能在ETL的阶段对此类数据进行预处理，将末尾的全角空格给剔除掉。如果业务系统对全半角的区别不感兴趣，也可以直接使用正则表达式将所有全角字符替换成相应的半角字符。</p>
<p style="text-align: right;">——<a href="http://www.imkevinyang.com/"><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/key-not-found" title="Key not found" rel="tag">Key not found</a>, <a href="http://www.imkevinyang.com/tags/sql-server" title="SQL Server" rel="tag">SQL Server</a>, <a href="http://www.imkevinyang.com/tags/%e5%85%a8%e5%8d%8a%e8%a7%92" title="全半角" rel="tag">全半角</a>, <a href="http://www.imkevinyang.com/tags/%e5%a4%84%e7%90%86%e5%bc%82%e5%b8%b8" title="处理异常" rel="tag">处理异常</a>, <a href="http://www.imkevinyang.com/tags/%e5%b1%9e%e6%80%a7%e6%9c%aa%e6%89%be%e5%88%b0" title="属性未找到" rel="tag">属性未找到</a>, <a href="http://www.imkevinyang.com/tags/%e6%8e%92%e5%ba%8f%e8%a7%84%e5%88%99" title="排序规则" rel="tag">排序规则</a>, <a href="http://www.imkevinyang.com/tags/%e7%a9%ba%e6%a0%bc" 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/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>
	<li><a href="http://www.imkevinyang.com/2009/05/sql-server%e4%b8%ad%e4%bf%ae%e6%94%b9%e8%87%aa%e5%a2%9e%e9%95%bf%e5%88%97%e7%bb%8f%e5%b8%b8%e9%9c%80%e8%a6%81%e7%94%a8%e5%88%b0%e7%9a%84%e9%85%8d%e7%bd%ae.html" title="Sql Server中修改自增长列经常需要用到的配置 (2009/05/24)">Sql Server中修改自增长列经常需要用到的配置</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/08/sql-server%e9%87%8d%e5%91%bd%e5%90%8d%e6%89%80%e6%9c%89%e5%a4%96%e9%94%ae%e7%ba%a6%e6%9d%9f.html" title="Sql Server重命名所有外键约束 (2010/08/02)">Sql Server重命名所有外键约束</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/2010/05/ssis%e8%b0%83%e7%94%a8%e5%ad%98%e5%82%a8%e8%bf%87%e7%a8%8b%e5%a4%b1%e8%b4%a5.html" title="SSIS调用存储过程失败 (2010/05/23)">SSIS调用存储过程失败</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/visual-studio%e7%bc%96%e8%be%91%e5%99%a8%e4%b8%80%e6%ac%a1%e7%bc%a9%e8%bf%9b%e5%8f%8d%e7%bc%a9%e8%bf%9b4%e4%b8%aa%e7%a9%ba%e6%a0%bc.html" title="Visual Studio编辑器一次缩进/反缩进4个空格 (2010/07/04)">Visual Studio编辑器一次缩进/反缩进4个空格</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>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/feed</wfw:commentRss>
		<slash:comments>3</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-08 18:11:54 -->
