再論 MongoDB 資料庫
先前分享過很多關於 MongoDB 的想法。
- 深夜淺談資料庫:MySQL / PostgreSQL / MongoDB / RethinkDB / TokuDB
- 深夜淺談 MongoDB : 預設的 MMAPv1 引擎
- MongoDB 的髒讀及偽讀
- MongoDB:Big query or Small queries
- 近日 MongoDB 二三事
MongoDB 的優點總結來說有三
- Dynamic schema
- Sharding
- Replica
首先,MongoDB 嚴格來說不是 Schemaless,而是 Dynamic schema,它本質仍然有 Schema。Dynamic schema 的優點眾所皆知,但缺點如下:
效能干擾
Dynamic schema 需要大量的 Index,而且 Index 很可能需要在運行期建立,所以在建立期會大量效能耗損。
資料正確性弱
因為維護 Dynamic schema 彼此間的數值參考 (reference) 很困難,再加上同名數值型態可能有異而造成查詢不一的問題。如 JSON 某 ID 值,有些資料可能以整數 (123),而有些資料可能以字串 (“123”) 儲存時,事後會造成很多查詢、比對、顯示的問題。
所以 Dynamic schema 等同於用開發方便性換取未來資料的維護性。
不過,Sharding 及 Replica 就是 MongoDB 的專長了。天生 Sharding + Replica 的特性,讓傳統 RDBMS (PostgreSQL / MySQL) 羨慕不少,畢竟 RDBMS 要做 Sharding + Replica 要耗用很多設計 (現在有很多工具可支援)。
但 MongoDB 的 Sharding + Replica 的方便設定也是用某些「東西」換來的。
Sharding 的實施方式有很多,MongoDB 是用類似 Proxy 中介層來處理,好處就是透明及方便,缺點就是所有讀寫都要經過這層,所以效能自然會耗損。
再者 Sharding 採用的是 Pre-sharding,也就是使用 Sharding key。這把 Sharding key 必須符合業務模式來預設指定,若未來發現不合時,就要 Re-sharding,這時大量資料搬動的效能耗損,幾乎會讓整體業務停擺。
很多人以為 MongoDB 適合大量寫入的場景,但嚴格來說不是。MongoDB 與 PostgreSQL / MySQL 對於資料一致性的要求級別不一。預設 MySQL 的要求嚴格高於 PostgreSQL,而 PostgreSQL 又高於 MongoDB。
MongoDB 的寫入級別有四,預設是 Acknowledged,即使提升至 Journaled 級別也與 PostgreSQL / MySQL 差一截,仍然會有資料遺失的風險,而且效能也較 Acknowledged 級別低許多。
所以 MongoDB 高寫入效能的假象某種程度是用資料可能損失換來的。
總結不利於 MongoDB 的需求 (不限於所列)
大量寫入
MongoDB 使用的 Sharding 方式,仍然有熱點問題。而且每個 Sharding 裡面的 Replica 只有 Primary 可以寫入。
高度使用 MapReduce 的需求
MongoDB 是單執行緒,我先前的文章有提到缺點。
複雜 Aggregation 的需求
天生的底層設計讓 Aggregation 無法太快。
ACID 的需求
這是 RDBMS 的強項,不是 MongoDB。
即時運算 (Real-time)
因為諸多設計的原因,造成 MongoDB 的效能變動較大,並不適合用於穩定即時的回應需求。
目前比較正確使用 MongoDB 的業務場景是 (不限於所列)
Data Variety (資料多樣性)
因為 Dynamic shcema,所以適合收集各種外界多變的資料,例如物聯網。之後再經過資料轉換的方式,轉儲存於 HBase 或 PostgreSQL/MySQL 等。
Cache (快取層)
可見很多架構在快取層混用 Redis / MongoDB。這很好理解,短期的 Key-value 熱點資料可以交由 Redis,而較複雜的就由 MongoDB。因為只處理短期快取,所以很多 MongoDB 的缺陷可以避免,再加上 Sharding + Replica 的優勢,非常容易擴展。