什么是Fact(事實)維度關系
開發過SSAS Cube的開發人員應該都知道,Cube的維度用法中有一種叫Fact(事實)關系類型,如下圖所示:
Fact(事實)維度關系就如同上面截圖中紅框中的描述一樣,指的是一張表即是事實表又是維度表,也就是數據倉庫中通常說的“退化維度”。比如在本例中我們的FactInternetSales(FactInternetSales表在數據源視圖中的FriendlyName是Internet Sales Facts,所以在Cube中FactInternetSales表顯示的是Internet Sales Facts這個名字如下圖所示)表既是事實表又是維度表,如下圖所示我們看到維度Internet Sales Order Details用的就是FactInternetSales表的列來構建的。
但是在Cube中我們發現FactInternetSales表也是事實表:
所以FactInternetSales表既是事實表又是維度表,維度Internet Sales Order Details和度量值組Internet Sales Facts其實都是引用的同一張數據庫表FactInternetSales,那么我們就可以在維度用法中將維度Internet Sales Order Details和度量值組Internet Sales Facts之間的關系定義為Fact(事實)關系如下圖所示:
從上圖中我們可以看到Fact(事實)關系並不像Regular(常規)和Referenced(引用)關系一樣要求設置維度表和事實表之間是通過什么字段來進行關聯的,Fact(事實)關系不需要進行任何關聯字段的設置。這是因為Fact關系默認會將維度表的Key屬性中KeyColumns的列和事實表的主鍵列進行關聯,其中事實表的主鍵列也可以是在SSAS項目數據源視圖(Data Source Views)中定義的邏輯主鍵(Logical Primary Key)如下圖所示,如果數據庫中的表或視圖沒有定義主鍵,其實也可以在SSAS的數據源視圖中為表或視圖定義邏輯主鍵。
如下圖所示我們看到維度Internet Sales Order Details的Key屬性是Internet Sales Order
而我們可以從下圖看到Key屬性Internet Sales Order中的KeyColumns包含了FactInternetSales表的SalesOrderNumber和SalesOrderLineNumber這兩列數據
而事實表FactInternetSales的主鍵列也是SalesOrderNumber和SalesOrderLineNumber這兩列
所以維度Internet Sales Order Details和度量值組Internet Sales Facts之間設置的Fact關系,實際上就是使用了FactInternetSales表的SalesOrderNumber和SalesOrderLineNumber這兩列做Join來進行Cube的相關運算的。
我們使用MDX語句可以查看到維度Internet Sales Order Details成功地切割了度量值組Internet Sales Facts的[Sales Amount]數據。
Fact(事實)維度關系的維度可以包含多張表
實際上維度Internet Sales Order Details如果包含了FactInternetSales表以外的表,也可以和度量值組Internet Sales Facts設置為Fact關系,如下圖所示我們將DimSalesTerritory(FriendlyName是Sales Territory)表的SalesTerritoryRegion列加入了維度Internet Sales Order Details作為一個屬性Sales Territory Region,所以實際上現在維度Internet Sales Order Details用到了兩張表FactInternetSales和DimSalesTerritory。
從下圖中可以看到,我們使用MDX語句成功地用Internet Sales Order Details維度的Sales Territory Region屬性切割了度量值組Internet Sales Facts的[Sales Amount]數據。
錯誤地配置Fact(事實)維度關系
我們前面說了Fact關系是通過維度的Key屬性的KeyColumns列和事實表的主鍵列做Join來進行Cube運算的。那么如果維度的Key屬性設置了錯誤的KeyColumns列,那么就會導致在處理Cube的時候Fact關系會報錯或得到不正確的計算結果。例如下圖中我們胡亂地更改了維度Internet Sales Order Details的Key屬性Internet Sales Order中的KeyColumns為FactInternetSales表的ShipDateKey和UnitPrice兩列。
我們可以看到在Cube的維度用法中Fact關系立馬出現了錯誤,提示事實表主鍵列的數據類型和維度表Key屬性中KeyColumns列的數據類型不一致。
所以正確地設置維度表Key屬性中的KeyColumns列對於Fact關系來說至關重要,要特別謹慎。
Fact(事實)關系和Regular(常規)關系有何不同
前面我們說了Fact維度關系就是用維度表Key屬性中KeyColmuns列和事實表的主鍵列做Join來做Cube計算的,那么實際上我們完全可以把Fact關系改為Regular(常規)維度關系,因為Regular關系實際上也是做維度表和事實表的鍵值Join進行Cube運算,只不過你要在Regular關系中指定用哪些列來做為Join列。比如下圖中我們將維度Internet Sales Order Details和度量值組Internet Sales Facts之間的關系從Fact改為了Regular,並指定使用維度Internet Sales Order Details中Key屬性Internet Sales Order的KeyColumns列SalesOrderNumber和SalesOrderLineNumber,映射到事實表的SalesOrderNumber和SalesOrderLineNumber列來做Regular關系的Join運算。
在處理Cube后,我們使用和前面相同的MDX做查詢,得到了和Fact維度關系相同的查詢結果:
這說明維度用法中的Fact關系完全可以由Regular關系來替代,那么為什么Cube中需要設置Fact關系呢?實際中我們測試下來,本例中將維度Internet Sales Order Details和度量值組Internet Sales Facts設置為Fact關系后,MDX的查詢速度要遠遠好於Regular關系,雖然MDX語句和查詢結果都是相同的,但是Fact關系的性能要比Regular關系好很多,那么說明Cube對Fact關系的運算是經過特殊優化過的,我們知道Fact關系的維度表和事實表都是同一張數據庫表,那么Cube在使用維度表切割事實表數據的時候肯定進行了更快捷的運算,這一點也是Fact關系的優勢所在。