04 文件設計基礎

03 Payload 與 Process 欄位 | 回到 MongoDB 資料建模設計 | 下一篇 → 05 索引與優化

這一段是整場的方法論核心:MongoDB 的 schema 要怎麼想,以及「link 還是 embed」的決策準則。

Schema Design in MongoDB(p.23)

Schema is defined at the application-level —— schema 定義在應用層,不是資料庫層。

  • Focus on the needs of the application —— 聚焦在應用的需求。
  • Not the abstract nature of the data —— 不是聚焦在資料本身的抽象結構。
  • Design is the part of each phase in its lifetime —— 設計貫穿應用的整個生命週期,不是一次定案。
  • 一句話總結:Schema design should focus on the application and not the data

講師展開:schema design 是「持續」的,不是一次性

  • 傳統關聯式的直覺是「一開始就定好 schema」。但 MongoDB 的一大優勢是靈活性(彈性):不需要在設計初期就把 schema 完全定死。
  • MongoDB 的 schema 本質上是「一份 JSON / 一個 document」,之後可以在應用的生命週期裡:
    • 增加欄位、調整欄位,成本非常低;
    • 隨業務演進逐步擴展。
  • 所以 schema design 不是某個時間點的動作,而是存在於應用整個生命週期裡。哪裡最能貼近需求、最快回應需求變化,就在哪裡調整。
  • 出發點永遠是 application 的需求mile 需求導向),而不是反過來從資料的抽象結構去推。目的是為資料找一個「榮譽存放處」——恰當地服務應用怎麼用它。

Three Considerations(p.24)—— 三大考量

分析需求時,圍繞三件事:

  1. The data the application needs —— 應用需要哪些資料。
  2. Application’s read usage of the data —— 應用怎麼讀這份資料。
  3. Application’s write usage of the data —— 應用怎麼寫這份資料。

講師的做法:在需求分析階段,先把「應用需要什麼資料、讀操作長什麼樣、寫操作長什麼樣」管理清楚,確立實體、實體之間的關係,再看哪些關係該合併(embed)、哪些該分開(link)。

  • 讀寫的權衡:要什麼樣的資料、要什麼樣的讀?→ 決定資料怎麼擺、要不要為讀去設冗餘(denormalize)。
  • 寫的形態:是簡單寫一張 document,還是要跨多個 document?
  • 根據讀寫的相對頻率與形態,決定合併或拆開、以及索引怎麼設(→ 05 索引與優化)。

決定兩個實體之間要 Link(存參照)還是 Embed(內嵌),問自己五個問題:

  1. Do I want the embedded info a lot of the time? —— 這份資料是不是「經常要一起被讀出來」?經常要 → 傾向 embed。
  2. Do I need to search with the embedded info? —— 需不需要「用這份內嵌資料去搜尋(當查詢條件)」?
  3. Does the Embedded info change often? —— 這份資料是否經常變動?經常變動且被很多地方冗餘 → 傾向 link(否則每次變動要改很多地方)。
  4. Do I need the latest version or the same version? —— 你要的是最新版,還是當時那一版?(呼應 06 設計模式 Design Patterns 的 Versioning。)
  5. Is the embedded info shared – really? —— 這份資料真的被共享嗎?如果只是看起來被共享、其實各自獨立,那 embed 反而簡單。

講師的判準口訣

  • 經常要被一起讀出的 → 盡量 embed(一次查詢就拿到,速度快)。
  • 經常需要獨立搜尋 / 經常變動 / 真正被大量共享的 → 傾向 link(避免冗餘資料到處要維護、避免更新一個地方要改很多份)。
  • embed 的代價是「勇於冗餘」:把一些外部欄位複製進主 document,讓查詢時不必再往外抓——值不值得,看讀取頻率與變動頻率的取捨。

What about an Invoice Address, link, or embed?

講師的推導:

  • 訂單/發票(invoice)裡的收件地址,該 embed 還是 link 到客戶(customer)的地址?
  • 關鍵在需求:開發票、看發票時,是否需要「那張發票當下的地址」?
    • 如果需求是「查訂單時要看到當時出貨的地址」→ 應該把地址 embed 進 invoice。因為客戶地址之後可能會變,但這張發票要保留的是開立當時的地址(同 06 設計模式 Design Patterns Versioning 的「當時版本 vs 最新版本」)。
    • 如果不需要看地址、或只要最新地址 → 可以只在 invoice 存一個發票 ID / 客戶參照,需要時再去 customer 撈(link)。
  • 結論回到需求:先問「你的應用需求是什麼」,再決定用哪種存法——順著需求去設計資料結構,而不是反過來讓資料決定需求。

小結

  • schema 定在應用層,focus on application not data;設計貫穿整個生命週期,可持續演進。
  • 三大考量:要哪些資料、怎麼讀、怎麼寫
  • link vs embed 的五問:常一起讀?要拿來搜?常變動?要最新還當時?真的共享?
  • 大原則:能 embed(常一起讀)就 embed;要獨立查/常變/真共享就 link。

→ 下一篇:05 索引與優化