維度的優化
- 確認屬性關系
- 有效的使用用戶自定義的層次結構
定義屬性關系
屬性關系定義了屬性之間的依賴關系,比如如果 A 有一個關聯的屬性 B, 那么就是 A -> B。比如,一個給定的屬性關系 City -> State, 如果當前的城市是 Seattle, 那么我們一定知道 State 一定是 Washington. 通常情況下,屬性之間的關系可能在原始維度表中有可能比較明顯,也有可能不是很明顯,但是還是可以利用起來做性能優化。比如默認情況下,所有的屬性都是關聯到 Key 的,這個時候的屬性關系表現的就是被稱之為 "Bush Attribute Relationship" - 可以理解為濃密的,比較粗野灌木叢狀的這種關聯關系。在這種 Bush Attribute Relationship 關系中,所有的樹干都是從 Key 關鍵屬性展開,但都同時都已自身屬性結束,這就是 "灌木叢屬性關系"。
那么我們可以基於數據之間本身自有的邏輯關聯來重新定義屬性之間的關系以優化性能。在這種情況下,如下圖所示 Model Name 定義了 Product Line 和 Subcategory (即知道了是哪一種 Model 那么就一定知道它是屬於哪一個 Product Line 和 Subcategory), 而 Subcategory 定義確定了 Category (即知道它是哪一種 Subcategory 那么就一定能確定它是屬於哪一種 Category; 或者理解為,這個 Subcategory 只會在一個 Category 中出現,不會同時出現在兩個 Category 中)。像這種屬性關系的定義一般都是多對一,或者 一對一的關聯關系 -
屬性之間的關系設計可以從兩個方面提升性能:
- 索引的構建和跨屬性查詢不需要都依賴於關鍵屬性 Key Attribute。
- 在屬性上的聚合能夠在查詢中和相關的屬性中重用。
可以對比上面的兩幅圖,比如需要獲取 Subcategory 和 Category 這兩個屬性,包括最后做一些聚合等操作。在第一個屬性關系中,在 Subcategory 和 Category 之間並沒有一個顯示的關系定義,查詢引擎必須首先要查詢到哪一個產品是屬於哪一個 Subcategory,然后再確定這個產品 Product 是屬於哪一個 Category,最后才能確定 Subcategory 和 Category 之間的關聯關系。BIWORK 在這里開個玩笑,比如張三這條記錄,記錄中有一個爸爸叫李四,還有一個爺爺叫王五 (當然張三,李四和王五背后的 KEY 肯定是可以唯一的),要搞清楚李四和王五之間的關系,或者如何通過李四找到李四的爸爸,就必須首先通過李四找到他的兒子張三,然后通過張三找到他的爺爺王五,這樣就知道王五是李四的爸爸了。
如果是通過這樣的一種方式來確定屬性之間的關系,比如說通常在 Office Excel 中通過一個層次結構去聚合和查看數據,如果這個維度比較大的話,那么這種查找關聯與確定下上層次之間的關聯關系的過程會非常消耗時間。相反,如果能夠重新定義屬性之間的這種關聯關系,那么在 PROCESS 處理階段內部索引被構建,並且索引信息中維護了他們之間的關系,因此分析服務很容易就知道哪些 Category 被哪些 Subcategory 所關聯,這樣效率會得到極大的提升。
同時在考慮定義屬性關系的時候,也要考慮屬性之間的關系是 Flexible (可變的) 還是 Rigid (固定的), 默認是 Flexible 的。
Flexible 是指在維度更新的時候,屬性之間的關系是可變的。比如 BIWORK 我之前在上海工作,現在到了北京,因此 Customer -> City 這種關系就是可變的。並且,在維度增量更新的時候,之前的聚合會被刪除掉然后重新計算。但是如果僅僅是新成員的增加,就不會刪除已有的聚合。
Rigid 是指維度更新的時候,屬性之間的關系也不改變,或者說也承諾不改變。如果發生改變了,那么在增量 Processing 處理的過程中就會發生錯誤。比如 Month -> Year 這種關系就是 Rigid 固定的。
但是要注意,屬性關系無論是定義成 Flexible 還是 Rigid 對查詢性能都沒有什么影響,只是一種手段。這種設計只是確保比如 Rigid 確實要做到兩個屬性關系是不可變的,應該跟我們預先設計保持一致。如果出現錯誤,說明某些數據的改變打破了我們預先的設計,應該引起我們的注意。
有效的使用層次結構
屬性如果僅僅只是保留在默認的屬性層次結構中的話,那么在聚合設計階段它們並不會主動使用到它們,不會發生真正的聚合。在查詢階段,如果包含了這些屬性的引用,這個時候也還是通過主鍵 Key Attribute 來匯總數據。這樣一來,沒有利用到聚合的好處,在查詢中對這些屬性層次結構的使用上性能將非常慢。
為了提升查詢性能,一般會通過 Aggregation Usage 屬性來配置聚合屬性的候選人 (這個以后再介紹)。在修改 Aggregation Usage 屬性之前,還要考慮到使用用戶自定義的屬性層次結構。
分析服務有兩種用戶自定義的屬性層次結構 - 自然層次結構和非自然層次結構 (Natural Hierarchy and Unnatural Hierarchy),它們各自的設計和性能特征都不相同:
自然層次結構 Natural Hierarchy - 在自然層次結構中的所有級別上的所有屬性,它們與其它從層次結構頂層到底層上的其它所有屬性都有着直接的或者間接的關聯關系。
非自然層次結構 Unnatural Hierarchy - 在層次結構中的至少兩個連續的層級上的屬性,它們彼此之間是沒有屬性關聯關系的。通常這種類型的層次結構也是用來為常用的屬性創建 Drill-down 鑽取導航路徑,但是它本身又沒有"自然層次"的特征。比如說,用戶可能需要通過由性別和教育構成的層級結構來瀏覽數據,但是性別和教育彼此之間沒有這種自然的關聯關系。
從性能的角度來考慮,自然層次結構的表現方式和非自然層次結構區別還是非常大的。在自然層級結構中,層次結構樹在層次結構存儲時將會被具體化或者磁盤化 Materialized。並且,參與到自然層次結構中的所有屬性都會被自動的成為聚合候選屬性。( 關於 Materialized 等概念可以參考索引視圖,索引視圖中也有這個概念。可以理解像表一樣存儲數據,把聚合結果和層次結構保存到磁盤上) 。
非自然層次結構不會磁盤化,並且結構中的屬性並不會自動的被選為聚合候選屬性。盡管沒有這種自然的關聯關系,但是從用戶的角度來說,有這種鑽取的層次路徑還是非常方便的,並且在 MDX 中通過導航函數也可以非常方便的導航和計算,所以還是可以起到一定的積極作用的。
更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server) 如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。