MongoDB 的預設讀寫引擎 (MMAPv1) 感覺不適合當資料庫。原因是資料庫常見的兩大應用場景 OLTP 及 OLAP ,MMAPv1 在達到某個階段時都很容易遇到障礙。

OLTP

OLTP 面對的是高併發的寫入及更新。可是 MMAPv1 天性就容易造成大量的記憶體碎片,進而產生大量的硬碟空間碎片 (資料寫回硬碟)。

記憶體碎片會造成記憶體的浪費,也意謂著 Cache hit rates 很低。硬碟空間碎片會造成硬碟容量浪費,也意謂著需要耗用更多 IO 來處理資料 (即浪費硬碟儲存不必要的資料,也浪費硬碟 IO,導致需要更多硬碟來應付需求)。

而當資料庫的容量超過記憶體時,系統勢必要花費額外的 CPU 及 IO 來交換,如此更加快 MongoDB 增機擴展的需求。

但 MongoDB 最擅長的增機擴展 (如 Sharding) 又面臨資料的偏性而不穩定,若處理的資料天性偏向集中於某處,那麼 hotspot 就會集中在集群中的某幾台機器,使得增機擴展無法線性成長,等同於要浪費更多的機器來補足,最終達到瓶頸而無法處理。

再加上 MMAPv1 沒有自動清理碎片的機制(它依賴作業系統),也沒有資料壓縮功能,這兩種其它資料庫常見處理碎片的手法它都不支援。

不過 MongoDB 有提供手動清理碎片的方式,只是非常耗系統資源,且效能可能會掉至原本的四分之三不到,而這通常不是 24x7 線上服務能接受的。

OLAP

MongoDB 因引入 Mapreduce 而宣稱進入 Big data 行列。不過至今其 Mapreduce 仍然是 read-lock 及 write-lock。也就是若 MongoDB 在處理 Mapreduce 時,無法有任何其它的讀寫操作,包括其它的 Mapreduce。

即使利用 Sharding 緩解,每個 Sharding 也都各自是 read-lock 及 write-lock 而難以完全發揮性能。所以你會看到很多奇奇怪怪的加快 Mapreduce 的技巧,這都是因為 MongoDB 的缺陷而讓程式設計師不得不 workaround。

而且 MongoDB 是單執行緒(single-thread)又無法跨進程溝通,所以無法引入目前最常見的 MVCC 無鎖設計,無疑讓問題雪上加霜。