MongoDB Schema 設計指南 (Part II) - 反正規化的威力


mongodb

MongoDB 反正規化的威力

上一次介紹的「MongoDB Schema 設計指南」之後,今天來介紹一下續集趴兔 (原文在此)。在上一篇文章中,已經介紹了一些基本的設計技巧,我們可以透過以下兩個問題幫助我們分析選用適合的 Schema Model。

  1. 在我們的參照實體中,需要 stand-alone (資料獨立性) 這樣的特性嗎?
  2. 對於參照實體的基數多寡,可以選定使用 one-to-few, one-to-many 或 one-to-squillions 哪一種模式?

如果上述的問題您還沒有非常清楚,那麼建議可以複習一下前一篇文章的介紹。接下來我們要介紹一些進階的 MongoDB Schema 設計方法,介紹利用 Two-Way Referencing (雙向參照) 與 Denormalization (反正規化) 這些技巧來使用 MongoDB,讓我們的查詢更有效率。

Two-Way Referencing (雙向參照設計)

Two-Way Referencing 我也不知道怎麼翻譯,所以先暫時叫做「雙向參照」吧!先回顧一下之前提到的 one-to-squillions (海量級關聯模式),可以快速在海量級母體中查詢資料。但是在兩個關聯實體中,有時候查詢的圍度與面向不同,有時候由 A 查 B,有時候由 B 查 A。這時候我們就需要雙向參照的設計模式,舉個工作單管理的例子如下:

上面儲存每個使用的的資料與目前擁有的工作單 (Tasks),然而每個工作單的集合如下:

上述工作單 Document 其中有個 owner 欄位,並且指向所屬的擁有者。這時無碖我們想要查詢某個人的工作單,或者由某個工作單查到所屬的使用者,都可以很方便地完成,人員 (person) 與工作單 (tasks) 皆保持資料一致性 (Stand-Alone)。那缺點呢?缺點就是一旦有資料關係需要變更,兩個物件內容都要進行更新,必須手動來同步關聯狀態。

Intermediate (媒介設計模式)

多對一反正規化 (Denormalizing from Many -> One)

這個方法應該是到目前為止,用到「反正規化」概念最深入的模式,主要將一對多模型進行反正規化,減少查詢的 Join 作動以提升效率。先舉個例子說明一下,比如一個「商品」可能由數個「組件」組成,是一個多對多的關係,如下:

若是我們想要很快地撈出「商品」與他所屬的「組件」名稱,在上述原本已經正規化的狀態下,就必須再去查詢 parts collection 才能獲得「組件名稱」。為了更有效率地進行查詢,可以透過反正規化來完成,我們將資料的儲存方式改成下面的範例:

上述我們直接在 parts 欄位放上我們常需要的 name 欄位,如此一來只要 Query 一個 Collection 就可以獲得我們想要的資訊,減少 Join 的執行,這樣的方式對於大量資料的查詢是很有幫助的。如此違反正規化的過程就稱為「反正規化」,缺點可以很清楚地發現,因為 name 被重複儲存記錄,維護的時候就很麻煩。反正規劃之後,若是要維持資料一致性,修改 name 欄位就必須更新所有地方。像是上述這樣的例子並不會很常更改「組件」實體的 name 欄位,整體獲得的效率是高過維護成本。

此外,如果要查詢每個組件的其他詳細資料,當然要用到 Join,在 MongoDB 裡面我們稱為 Application-level Join,可以再次撈取另一個 Collection 進行組合,如下:

一對多反正規化 (Denormalizing from One -> Many)

這個例子前面介紹的概念其實差不多,在上述的案例,假設我們想快速查詢「組件」資訊,又想要查詢這些「組件」所屬的「商品」名稱,如果想要加速查訊效率,不想要使用 Application Join,那就是對「商品」的名稱欄位進行反正規化。修改後的 Schema 如下:

上述例子將「商品」的 name 欄位重複設定在「組件」中的 product_name 欄位中,反正規化之後就可以大幅提升查詢效率。當然失去資料的一致性,在維護上要付出的代價是相同的,根據實際使用的情境進行反正規化,在 MongoDB 或其他分散式資料庫都是常見的手法。在進行反正規化之前,我們必須理解以下兩個重要的特性:

  • 反正規劃之後,就會失去資料的一致性 (Stand-Alone)
  • 在讀取頻率高,寫入頻率低的情況下,進行反正規化才有意義

系統需求經過分析之後,將更新頻率不高的欄位進行反正規劃,會是不錯的選擇。在 Query 的便利性與效率會大大提昇,是不是很有趣呢?今天就先介紹到這,下次再見囉。YY

MongoDB 系列文章

Facebook 留言

廣告

樂樂童鞋