程式扎記: [ MangoDB 文章收集 ] MangoDB 介紹

標籤

2012年5月28日 星期一

[ MangoDB 文章收集 ] MangoDB 介紹

來源自 這裡 
前言 : 
NoSQL 是一個縮寫,含義從最初的 No-SQL 到現在已經成為了 Not-Only-SQL。確實後面一種解釋比較符合 NoSQL 的使用場景. 現在網路上被人所知的 NoSQL 資料庫可以在這個網頁(http://nosql-database.org)看到。這個列表林林總總一大堆,要選擇哪個資料庫入手呢? 

在這些候選名單中我選擇了 MongoDB。因為它最近在 RoR 社區中的露臉率比較高,網頁文檔完善,並且專案主頁的設計也不錯. 在陳述 MongoDB 的特性之前,還是給第一次接觸 NoSQL 的人提個醒:不要意圖用 NoSQL 全盤取代 SQL 資料庫。非關聯資料庫的出現不是為了取代關聯資料庫。具體的說,MongoDB 並不支援複雜的事務,只支援少量的原子操作,所以不適用於“轉帳”等對事務和一致性要求很高的場合。而 MongoDB 適合什麼場合,請繼續閱讀. 
 

文檔型資料庫初探 : 
關聯資料庫比如 MySQL,通常將不同的資料劃分為一個個“表”,表的資料是按照“行”來儲存的。而關聯資料庫的“關係”是指通過“外鍵”將表間或者表內的資料關聯起來。比如 文章-評論 的一對多關係可以用這樣的表來實現 : 
  1. posts(id, author_id, content, ... )  
  2. comments(id, name, email, web_site, content, post_id)  
實現關聯的關鍵就是 comments 表的最後一個 post_id 欄位,將 comment 資料的 post_id 欄位設為評論目標文章的 id 值,就可以用 SQL 語句進行相關查詢(假設要查的文章 id 是 1): 
SELECT * FROM comments WHERE post_id = 1;

相對於關聯資料庫的行式儲存和查詢,MongoDB 作為一個文檔型資料庫,可以支援更具層次感的資料。上面舉的 文章-評論 結構,在 MongoDB 裏面可以這樣設計 : 
  1. {  
  2.   _id : ObjectId(...),  
  3.   author : 'Rei',  
  4.   content : 'content text',  
  5.   comments : [ { name : 'Asuka'  
  6.                  email : '...',  
  7.                  web_site : '...',  
  8.                  content : 'comment text'} ]  
  9. }  
comments 項是內嵌在 post 項中的(作為陣列)。在 MongoDB 中,一個資料項目叫做 Document,一個文檔嵌入另一個文檔(comment 嵌入 post)叫做 Embed,儲存一系列文檔的地方叫做 Collections。順便一提,MongoDB 中也提供類似 SQL 資料庫中的表間關聯,叫做 Reference. 

用文檔型資料庫儲存文檔 : 
可以看到,文檔性資料庫從儲存的資料項目上就跟 SQL 資料庫不同。在 MongoDB 中,文檔是以 BSON 格式(類似 JSON)儲存的,可以支援豐富的層次的結構。由於資料結構的表達能力更強,用 MongoDB 儲存文檔型資料可以比 SQL 資料庫更直觀和高效. 

簡化模式設計 : 
在 SQL 資料庫中,為表達資料的從屬關係,通常要將表間關係分為 one-to-one,one-to-many,many-to-many 等模式進行設計,這通常會需要很多鏈結表的輔助。在 MongoDB 中,如果關聯文檔體積較小,固定不變,並且與另一文檔是主從關係,那麼通常可以嵌入(Embed)主文檔. 

這類場景的有時單個資料項目體積很小,但是數量巨大,與之相應的是查詢成本也會上升。如果將這些小資料嵌入所屬文檔,在查詢主文檔時一併提取,查詢效率要比 SQL 高,後者通常需要開支較大的 JOIN 查詢。並且根據文檔介紹,每個文檔包括 Embed 部分在物理硬碟上都是儲存在同一區域的,IO 部分也會比 SQL 資料庫快。(注,MongoDB 有單文檔大小限制) 

動態的文檔模式 : 
MongoDB 中的文檔其實是沒有模式的,不像 SQL 資料庫那樣在使用前強制定義一個表的每個欄位。這樣可以避免對空欄位的無謂開銷. 例如兩個用戶的聯繫資訊,A 用戶帶有 email 不帶 url,B 用戶帶有 url 不帶 email。在 SQL 資料庫中需要為兩個資料項目都提供 email 段和 url 段,而在 MongoDB 中可以這樣保存 : 
  1. [ { name : 'A', email : 'A email address' }, { :name : 'B', url : 'B url address' } ]  
MongoDB 另外一些特點 : 
- JSON 文檔式查詢 
MongoDB 的查詢語言看起來是這樣的 : 
> db.users.find( { x : 3, y : "abc" } ).sort({x:1})

這是在 MongoDB 內置的 JavaScript 控制臺上的查詢,表示在名為 users 的 Collections 中查找 x = 3,y = “abc” 的文檔,並且以 x 遞增的順序返回資料. JSON 文檔式查詢會讓寫慣應用層代碼的開發者眼前一亮,但對於精通 SQL 查詢的關聯資料庫管理員來說就是一個新的挑戰了! 

- 對分散式的支援 
MongoDB 對大型網站的最大吸引力也許來源於其對分散式部署的支持。當今互聯網最流行的資料庫 MySQL 在網站擴大到一定規模之後就會遇到擴展瓶頸,解決方案通常是分表分庫、配置主從資料庫。很多互聯網開拓者前仆後繼的為資料庫擴展性奮鬥,留下了一頁頁的寶貴經驗. 

既然年復一年的有人為同一個問題奮鬥,為什麼不將這些問題在資料庫層面就解決了呢?而 MongoDB 的優勢之一就是內建對分散式的支持 : 
 

總結 : 
沒有銀彈,這個教誨已經提過太多。由於缺乏對事務的支援,MongoDB 不太適用于金融等行業的關鍵部分。但對於現在要應對海量細資訊的 Web 網站來說,MongoDB 可能恰好出現在了正確的時代。NoSQL 的無模式,能讓網站開發的迭代更輕盈;MongoDB 對分散式的支援,可以緩解網站快速成長時在資料庫端的瓶頸疼痛. 不要激進的用 NoSQL 替代所有 MySQL 應用,激進的 NoSQL 化只會像5年前的 all rewrite by RoR 浪潮一樣,耗費不必要的精力。但在新專案開發之初,可以考慮是否更適合使用 NoSQL.

1 則留言:

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!