關聯 vs 文件模型 (Relational vs Document)

★★★★★Reviewed

FromDDIA

📚 From the Books

關聯 vs 文件模型 (Relational vs Document)Data Models

兩種主流資料模型。文件模型用巢狀結構換取局部性 (locality) 與「一對多」的自然嵌套;關聯模型用正規化與 join 把「多對多」表達得乾淨。選哪個,本質是在問你的資料「關係長什麼樣、查詢怎麼進來」。

🧠 Intuition

TIP

一句話分辨:資料像一棵(一份履歷、一張訂單連同明細)→ 文件模型;資料像一張(人連到公司、公司連到城市、彼此互相引用)→ 關聯模型。模型選錯,就是天天在跟資料的形狀對抗。

⚖️ Tradeoffs

局部性 (Locality) — 文件模型的主場
  • 一份文件存成連續一塊,讀整份(如整張訂單)只要一次存取,省掉多表 join 的隨機 I/O。
  • 但局部性是雙面刃:通常得讀整份文件才能取其中一小段,文件越大越浪費。
  • 更新也常需重寫整份文件(只有「不改變大小」的原地改才便宜)。
  • 結論:當應用「一次就要載入整棵樹」時,局部性是實打實的效能優勢。
一對多 — 文件自然嵌套,關聯要拆表
  • 一份履歷有多段學歷、多個職位、多項技能——這是天然的一對多樹狀結構。
  • 文件模型:直接把它們當陣列嵌在文件裡,結構即資料、所見即所得。
  • 關聯模型:得拆成 positions、educations 等子表,用外鍵連回主表,查詢時再 join 回來。
  • 對「一對多 + 整棵一起讀」的場景,文件模型語意更貼、程式更短。
多對多與 join — 關聯模型的主場
  • 一旦出現多對多(推薦人連到別的使用者、貼文被多人標註),文件模型只能存「引用 (reference)」,再在應用層手動 join。
  • 應用層 join 不但程式碼複雜,還少了查詢優化器、index 等資料庫級別的支援。
  • 關聯模型的 join 是一等公民,多對多、遞迴關係都交給查詢優化器處理。
  • 關係越「網狀」、join 越多,關聯模型(或圖模型)越划算。
schema-on-read vs schema-on-write
  • 文件庫多為 schema-on-read:寫入不檢查結構,讀取時由應用程式解讀——彈性高、適合異質或常變的資料,但錯誤往讀取時延後爆發。
  • 關聯庫多為 schema-on-write:寫入時強制檢查 schema,像靜態型別——一致性強,但改 schema 要 migration。
  • 關鍵差異在「結構的隱性 vs 顯性」:文件庫的 schema 其實藏在應用程式碼裡,只是沒寫進資料庫。
  • 欄位高度異質、或迭代極快的早期專案 → schema-on-read 較順手;資料契約穩定、多方共用 → schema-on-write 較安全。

🔑 Takeaways

✍️ My Notes

2026-07-01

  • Q: 既然文件模型「讀整份很快」,為什麼不一律用它?
  • A: 因為它快的前提是「資料是樹、且你真的要整棵讀」。一旦關係變成網狀(多對多、跨文件引用),文件模型就退化成在應用層手刻 join,失去資料庫優化器的所有幫助,且容易出現資料不一致。它的局部性優勢也會反咬——文件越長大,每次讀寫整份的成本越高。所以選型要看資料的關係形狀,而非單純的讀寫速度。

📖 Further Reading

🔗 Dive Deeper