當資料格式未達到所需查詢操作的理想時,對一個或多個資料儲存庫中的資料產生預先填充的檢視。 此方法能支持高效的查詢與資料擷取,並提升應用程式效能。
內容和問題
在儲存資料時,開發人員和資料管理員通常會優先考量資料的儲存方式,而非讀取方式。 所選儲存格式通常反映資料格式、資料大小與完整性管理的要求,以及所使用的儲存類型。 例如,當你使用 NoSQL 文件儲存時,通常會將資料表示為一系列彙總,每個彙總包含該實體的所有資訊。
然而,這種做法可能會對查詢產生負面影響。 當查詢只需某些資料實體的數據子集時,例如幾位客戶的訂單摘要而不包含所有訂單詳細信息,它仍需提取相關實體的完整數據,以獲得所需的資訊。
在讀取時新增索引或重新調整查詢,並不總是能解決這種低效率問題。 許多儲存裝置無法針對任意的讀取模式重新索引,否則會影響寫入效能。 跨實體聚合在查詢時仍然相當昂貴。 有些商店天生就限制了查詢功能。 由於這些限制,僅在原始碼儲存庫內優化讀取路徑往往是不夠的。
解決方案
為了支持有效率的查詢,常見的解決方案是事先產生一個視圖,將資料以適合所需結果集的格式呈現。 具體化檢視圖樣描述在源數據格式不適合查詢、生成適合查詢的操作過於困難,或由於數據或數據存放區的性質導致查詢效能不佳的環境中,生成預先填充的數據檢視。
在此模式中, 物質化檢視 是一種讀取模型或投影,持續保存來自一個或多個來源儲存庫的資料。 專用的應用程式元件或資料管線可以維護該投影,甚至可跨越儲存區邊界。 查詢端將投影視為唯讀。 這種架構概念比資料庫原生的物質化視圖物件更廣泛,後者由資料庫引擎根據自身的功能限制定義、儲存與刷新。
這些實體化檢視僅包含查詢所需的資料,讓應用程式能快速取得所需資訊。 除了聯結數據表或合併數據實體之外,具體化檢視還可以包含計算結果列或數據項的目前值、結合值或對數據項執行轉換的結果,以及指定為查詢一部分的值。 實體化檢視甚至可以針對單一查詢進行優化。
一個關鍵點是,具體化的視圖及其包含的資料完全可拋棄,因為它們可以從原始資料儲存庫完全重建。 查詢端的取用者不會直接更新視圖。 相反地,它是由專用元件、資料管線或資料庫引擎來維護,因此屬於專用快取。
當視圖的來源資料變更時,視圖必須更新以包含新資訊。 你可以排程自動更新,或在系統偵測到原始資料變更時進行。 在某些情況下,你可能需要手動重新生成檢視。 下圖展示了 Materialized View 模式的使用範例。
問題和考慮
在決定如何實施此模式時,請考慮以下幾點:
查看刷新策略。 理想情況下,視圖會在顯示來源資料變更的事件後重新生成,儘管若原始資料快速變動,這種方式可能導致過多的開銷。 或者,請考慮使用排定的工作、外部觸發事件或手動動作來重新生成檢視。
重新整理行為。 判斷實作是進行完整重建還是逐步套用變更。 你還需要決定刷新作業是否會阻止讀取。
這些決策決定查詢是否回傳可能過時的物質化資料、將物質化資料與未處理的原始碼變更合併以返回目前結果,或繼續提供最後完整版本直到更新結束。
刷新訊號可靠性。 如果觸發視圖再生的啟動訊號遺失或延遲——例如錯過變更導出事件或排程任務失敗——視圖就會靜默地提供陳舊的結果。 監控刷新新近度,並在瀏覽年齡超過可接受的陳舊視窗時警示。
重新整理運算成本。 重新生成視圖會消耗與來源資料量及轉換複雜度成正比的運算資源。 對於快速變動的原始資料進行事件驅動刷新,或是對大型分析檢視進行完整重建,更新的計算成本可能成為重要的成本驅動因素。 調整刷新頻率與範圍,以平衡資料新鮮度與計算支出。
事件溯源相依性。 在某些系統中,例如使用 事件溯源模式 來維護只修改資料事件的儲存庫,通常需要實體化的檢視。 藉由檢查所有事件來判斷當前狀態,預先填充視圖可能是從事件庫獲取資訊的唯一方法。 如果你沒有使用事件溯源,可以考慮物化檢視是否有幫助。 具體化檢視通常針對一個或少數查詢量身打造。 如果使用許多查詢,具體化檢視可能會導致無法接受的儲存容量需求和記憶體成本。
資料一致性。 在產生檢視圖時,以及如果此過程在排程內進行,更新檢視時,請考慮對資料一致性的影響。 如果原始資料與檢視產生同時改變,檢視中資料的複製品與原始資料不完全一致。 最大過時視窗是刷新間隔或事件處理延遲的直接結果,因此在選擇事件驅動、排程或手動刷新前,請先定義可接受的陳舊狀態。
查看儲存位置。 檢視不一定位於與原始數據相同的存放區或分割區中。 你可以將幾個不同分割的子集合併。
遺失時重建。 如果視圖遺失,可以重新建置。 因此,如果視圖是暫態的,且僅用於反映資料當前狀態以提升查詢效能,或提升可擴展性,你可以將其儲存在快取或較不可靠的位置。
然而,如果重新整理程序本身在中途失敗——例如排程的重新產生任務當機——請判斷工作負載應提供先前的完整視圖、部分更新的視圖,還是在重新產生成功之前完全不提供任何視圖。
最安全的做法通常是採用原子式發佈或版本化替換,也就是說,在您建置並驗證新視圖的同時,工作負載會持續使用上一個完整視圖來提供服務。 驗證完成後切換到新視圖。
計算欄位。 在定義具體化視圖時,應根據現有資料項目的計算或轉換、查詢中傳遞的值,或適當時將這些值組合加入資料項目或欄位,以最大化其價值。
查看索引。 如果儲存機制支援,請考慮為具體化檢視編製索引,以進一步提升效能。 許多關聯式資料庫支援檢視的索引。 然而,檢視圖的索引維護會在每個刷新週期中增加寫入路徑開銷,因此需在讀取效能提升與額外的刷新時間及計算成本之間取得平衡。
視圖存取控制。 當實體化檢視被用來限制特定消費者可見的資料子集時,例如安全或隱私考量,檢視庫必須執行與來源資料相同或更嚴格的存取控制。 你的刷新管線必須排除非預期的欄位或列,因為一個視圖若意外包含超出預期範圍的資料,可能會暴露受保護的資料。
視圖中的資料生命週期。 將來源資料的保留與刪除需求套用至每個具體化檢視。 在規定期限內同步來源刪除與遮蔽,並將每個檢視納入合規監控。 欲了解更多資訊,請參閱 Microsoft Purview 的資料治理與安全基準。
檢視生命週期管理。 視圖定義應視為可部署的產物,透過原始碼控制與 CI/CD 管線管理,尤其當視圖是以宣告式定義時。 若無生命週期管理,視圖定義可能在不同環境間漂移,導致開發、暫存與生產間的查詢行為不一致。
使用此模式的時機
當下列情況時,請使用此模式:
- 你需要建立難以直接查詢的資料視圖,或是查詢必須非常複雜,才能擷取以正規化、半結構化或非結構化方式儲存的資料。
- 你想建立可重建或暫時快取投影,以提升查詢效能,或塑造用於建構 UI 、報表或顯示資料傳輸物件的資料。
- 你需要支援與資料存放區的連線不一定隨時可用的間歇性連線或離線情境。 在這種情況下,你可以將視圖快取到本地。
- 你想要簡化查詢,並以不需要了解原始資料格式的方式,讓資料暴露給實驗用。 例如,藉由聯結一或多個資料庫中的不同數據表,或 NoSQL 存放區中的一或多個網域,然後將數據格式化以符合其最終用途。
- 你想要提供對來源資料中特定子集的存取權,這些資料在安全或隱私考量下,不應該普遍被存取、開放修改或完全公開給使用者。
- 你想要橋接不同的資料儲存庫,以發揮它們各自的特性。 例如,你可以用一個高效的雲端儲存庫作為參考資料儲存,並用一個關聯式資料庫提供良好的查詢和讀取效能來保存具體化的視圖。
- 使用微服務時,保持它們鬆散耦合,包括資料儲存。 具體化檢視能幫助你整合服務中的數據。 如果具體化視圖不適合你的微服務架構或特定情境,可以考慮設定明確界線,與 領域驅動設計(DDD) 相符,並按需彙整資料。
在下列情況下,此模式可能不適用:
- 源數據簡單且容易查詢。
- 源數據會非常快速地變更,或不需要使用檢視即可存取。 在這種情況下,避免建立檢視時產生的處理負擔。
- 一致性是高優先順序。 觀點可能不總是與原始數據完全一致。
工作負載設計
架構設計人員應該評估具體化檢視模式如何用於其工作負載的設計,以解決 Azure 良好架構架構支柱中涵蓋的目標和原則。 例如:
| 支柱 | 此模式如何支援支柱目標 |
|---|---|
| 效能效率 可透過調整、數據和程式碼的優化, 有效率地協助您的工作負載符合需求 。 | 具體化檢視會儲存複雜計算或查詢的結果,而不需要資料庫引擎或用戶端重新計算每個要求。 此設計可減少整體資源耗用量。 - PE:08 數據效能 |
如果此模式在一個支柱內部引入取捨,請將它們與其他支柱的目標進行考量。
Example
考慮一個銷售應用程式,將訂單、OrderItem 和 Customer 實體存入 Azure 資料表儲存體。 訂單依顧客編號劃分,依訂單編號劃分商品,並依區域劃分顧客。 這些鍵值支援應用程式的營運存取模式,但依產品分組的銷售報告必須跨區讀取資料並合併成應用程式碼。
下圖顯示一個具體化的視圖,儲存電子產品類別中每項產品的總銷售額及獨立購買客戶數量。 來源資料列和摘要值僅為示意之用,並非用於所示總計的完整輸入資料集。
背景程序會讀取所需的來源實體,將訂單項目與其訂單及客戶建立關聯,並按產品彙總銷售資料。 它會為每位顧客每件產品計算一次,即使該顧客有多個訂單或訂單線。 該程序將結果寫入一個獨立的摘要表,產品類別為 PartitionKey ,產品 ID 為 RowKey。 此摘要表是應用程式維護的投影,而非資料庫原生的物質化視圖。
儀表板則可以查詢電子分區,而不必每次請求重複跨分區讀取與彙整。 查詢單一產品時會同時提供這兩個鍵。 關於這些鍵對查詢效能的影響,請參見 查詢設計。
依據符合報告可接受的過時時間範圍的排程更新摘要。 在發佈新版本前,請先建立並驗證,讓讀者在重建時仍能繼續使用先前的完整版本。 重新整理仍會產生跨分割區讀取和彙總成本,但重複執行的報表查詢可重複使用該結果。 來源變更要等到後續的重新整理納入這些變更後才會顯示。
下一步
- 建立索引檢視 說明 SQL 資料庫如何透過在檢視上建立索引來持久化計算出的檢視結果。
- Azure Cosmos DB for NoSQL 中的變更摘要設計模式說明變更摘要取用者如何維護具體化檢視。
- 具體化檢視概觀 說明 Azure Data Explorer 中的具體化檢視。
- Azure Managed Redis 可以將預先計算的查詢結果快取成位於持久性資料存放區前方的讀取最佳化層。
- Azure 資料表儲存體 可以儲存由應用程式邏輯或背景程序產生的預先計算檢視資料。
相關資源
當您實作此模式時,下列模式也可能相關:
- 命令和查詢責任隔離 (CQRS) 模式。 使用此方法來更新具現化檢視中的資訊,以響應基礎數據值變更時所發生的事件。
- 事件來源模式。 搭配 CQRS 模式使用,以維護實體化檢視表中的資訊。 當實體化視圖的資料值是基於變更時,系統可以啟動描述這些變更的事件,並將其儲存在事件儲存中。
- 索引數據表模式。 具體化檢視中的數據通常是由主鍵組織,但查詢可能需要藉由檢查其他欄位中的數據,從這個檢視擷取資訊。 使用此模式為不支援原生次級索引的資料儲存建立次要索引。