2015年1月5日 星期一

1.MongoDB介紹

MongoDB是10gen開發出來的的NoSQL資料庫,而NoSQL是Not Only SQL 的縮寫。MongoDB是用來處理大數據級的資料庫,而他是以文本的方式儲存的資料庫,我在早年曾經開發LotusNote的應用程式,那是我認識的第一套文本資料庫。


Mongo的資料體結構是以 Key,Value組合的,儲存的方式與Json格式完全相同,另外多了很多的靈活性,也就每一筆文件的是欄位的型態是不一定的欄位的存在性也是不一定的。如果你學過Relation DataBase一定會很困惑,因為MSSQL、MySQL教我們要先設定Table Schema後,明確定義Table的Column和其型態,有利於資料整理、資料存儲、並執行正規化的行為…等。

但在文本資料庫並沒有這樣子的限制,不過我認為雖然有這樣的彈性還是乖一點用Relation DataBase的設定概念來設計你的MongoDB資料庫。不然有一天一定天下大亂的。

為什麼要學習MongoDB或是他有什麼樣的特色呢?

1.MongoDB可以處理資料庫為 T級量 的資料庫,也就是處理大數據的資料庫。

2.分散式的資料庫模式,可以把眾多資料庫串聯後處理大數的資料。

當然在使用MongoDB也有很多不便之處

1.Console畫面操作對有些人來說是很煩人的,當然也有視窗化的工具(http://robomongo.org/)

2.對不熟悉JavaScript開發的人員來說,學習上的瓶頸可大了,因為Monogo是基本Javascript & JSON的資料庫



MongoDB的基本術語我們與Relation DataBase術語對照說明

Relation DataBase               MongoDB

--------------------------------------------------------------------------
資料庫(Database)                          DataBase
資料表(Table)                               Collection
資料(Record/Row)                        Document
欄位(Column)                                Field
主索引(PK)                                   _id
function                                        function ( )
stored procedure                           mapreduce 
--------------------------------------------------------------------------

請不要強記以上的對照關系,因為我只是想讓大家大致上了解二者資料庫的功能對映而以。

MongoDB存儲資料格式

在MongoDB是以 Json 格式存儲資料的,也就是所謂的Document其內容如下


{
     _id:"A001",
     name:"Canred",
     age:30,
     email:[
                   'canred.chen@gmail.com',
                   'canred.chen@ooo.com'
           ]
}

_id是PK,這一個欄位如果你沒有指定的話,系統會自動的生成;email的欄位是一個Array型態可以儲存多筆子文件。

在使用MongoDB時,有一些文件你必須先了解,以下內容我是轉載於
http://www.infoq.com/cn/news/2013/11/mongodb-things

http://www.csdn.net/article/2012-11-15/2811920-mongodb-quan-gong-lue

我先把幾個比較重要的知識標記出來。

32位vs 64位現在大多數的服務器都對32位操作系統實現支持,更有許多新型硬件支持著允許更多RAM的64位操作系統。MongoDB也同時發布了32位及64位兩個版本的數據庫。歸結於MongoDB使用的內存映射文件,32位版本只支持2G數據的存儲。對於標準的Replica Set,MongoDB只擁有單一的處理策略—— mongod。如果你想在未來儲存2G以上的數據,請使用64位版本的MongoDB。如果擁有分片安裝,那麼32位版本同樣可以使用。
總結:使用64位版本或者理解32位版本的限制。
文件大小限制
不同於RDBMS把數據儲存在行與列中,MongoDB的數據是儲存在文件中的。這些文件使用二進制存儲形式,其格式為類似JSON格式的BSON格式。和其它的數據庫一樣,單個文件的儲存大小是有限制的。在舊 ​​版本的MongoDB中,單個文件都限制在4M以內。而新版本的MongoDB單文件已經支持到16M大小。這樣的限制也許是令人厭煩的,但是10gen的意見是:如果這項設置不停的困擾到你,那麼是否你 ​​的設計模式存在著問題;或者你可以使用文件無大小限制的GridFS
這種情況通常的建議是避免存儲過大的文件,不定期的更新數據庫中存儲的各種對象。而像Amazon S3或者Rackspace Cloudfiles這樣的服務通常可能會是更好的選擇,而非必要情況下最好別讓基礎設施陷入過載。
總結:把每個文件保持在16M以下,那麼一切都好。
Canred補充:BSON格式也就是JSON資料以二進製的方式保存,並且重新規劃存儲的空間以利快速搜尋與磁碟空間的配置。
寫入失敗
MongoDB在默認的情況下允許高速的寫入和更新,而付出的代價就是沒有明確的錯誤通知。默認情況下多數的驅動都在做異步、“不安全”寫入——這就意味著驅動程序不能立即反饋錯誤信息,類似於MySQL的INSERT DELAYED。如果你想知道某個事情是否成功,你必須使用getLastError手動的檢查錯誤信息。
某些情況下如果你需要在錯誤發生後立刻得到錯誤信息,即:大多數的驅動中都很容易實現同步“安全”查詢。這將謀殺掉MongoDB不同於傳統數據庫的優點。
如果對比“完全安全”的同步寫入你需要多一點性能,同時還想要一定程度的安全,那麼你可以使用getLastError with'j'讓MongoDB只到一份日誌提交後再發出錯誤報告通知。那麼日誌將以100毫秒一次的速度輸出到磁盤,而不是60秒。
總結:如果必須要寫入確認,你可以使用安全寫入或getLastError。Canred補充:程序的朋友們要特別注意db.getLastError()的方法。
數據結構模型的弱化不等於沒有數據結構模型(非常重要)
RDBMS一般都擁有一個預定義的數據結構模型:表格的行和列,每個字段都擁有名稱和數據類型。如果你想給其中一行加一列,那麼你必須給整個表格都添加一列。
MongoDB則是移除了這個設置,對於Collection和文件沒有強制的模型限定。這有益於快速開發及簡易修改。
當然這不意味著你就可以無視結構模型的設計,一個合適的結構模型可以讓你獲得MongoDB的最佳性能。趕快閱讀MongoDB文檔,或者觀看這些結構模型設計的相關視頻吧!Schema Design Basics
Schema Design at Scale
Schema Design Principles and Practice
總結:設計結構模型並充分利用MongoDB的特色。
默認情況下修改語句修改的只是單個文件在傳統的RDBMS中除非使用LIMIT子句,修改語句作用的將是所有匹配的地方。然而MongoDB每個查詢上都默認使用等價“LIMIT 1”的設置。雖然無法做到“LIMIT 5”,但是你可以通過下面的語句整個的移除限制:
db.people.update( {age: {$gt: 30}} , {$set: {past_it: true}}  , false, true)
同樣在官方的驅動中還有類似的選項—— ' multi ',也就是最後一個 true
總結:可以通過指定多個文件的multi為true來完成多文件修改
查詢區分大小寫
字符串的查詢可能不按預期的那樣發展—— 這歸結於MongoDB默認區分大小寫
例如:db.people.find({name: 'Russell'})與db.people.find({name: ' russell'})是不同的。在這裡最理想的解決方案就是對需要查詢數據進行確認。你也可以通過正則表達式進行查詢,比如:db.people.find({name:/Russell/i}),但是這樣會影響到性能。
總結:查詢是區分大小寫的,在犧牲速度的情況下可以利用正則表達式。Canred補充:所以在一個文件的name,NAME是不一樣的Filed如下是允許的
{
    _id:1
    name:"canred",
    NAME:"陳慧鴻"}
對輸入的數據無容錯性當你嘗試向傳統數據庫插入錯誤類型的數據,傳統的數據庫一般會把數據轉換成預定義的類型。然而這在MongoDB中是行不通的,因為MongoDB的文件是沒有預定義數據模型的。這樣的話MongoDB會插入你輸入的任何數據。
總結:使用準確的數據類型
關於鎖當資源被代碼的多個部分所共享時,需要確信鎖必須要確保這處資源只能在一個地方被操作。
舊版本的MongoDB (pre 2.0)擁有一個全局的寫入鎖。這就意味貫穿整個服務器中只有一個地方做寫操作。這就可能導致數據庫因為某個地方鎖定超負載而停滯。這個問題在2.0版本中的得到了顯著的改善,並且在當前2.2版本中得到了進一步的加強。MongoDB 2.2使用數據庫級別的鎖在這個問題上邁進了一大步。同樣值得期待的Collection級別的鎖也計劃在下一個版本中推出。
儘管如此,Russell還是認為:大多數受此限制的應用程序於其說是受MongoDB影響,還不如說是程序本身的問題來的更直接​​。
總結:使用最新的穩定版本才能獲得最高的性能。
沒有join語句MongoDB不支持join:如果你想在多個Collection中檢索數據,那麼你必須做多次的查詢。
如果你覺得你手動做的查詢太多了,你可以重設計你的數據模型來減少整體查詢的數量。MongoDB中的文件可以是任何類型,那麼可以輕易的對數據進行De-Normalize。這樣就可以讓它始終和你的應用程序保持一致。
總結:沒有join不妨看一下如何設計數據結構模型
JournalingMongoDB使用內存映射文件並且每60秒向磁盤輸出一次通知,這就意味著最大程度上你可能丟失60秒加上向硬盤輸出通知這段時間內所有的數據。
為了避免數據丟失,MongoDB從2.0版本起就添加了Journaling(默認情況下開啟)。Journaling把時間從60秒更改為100ms。如果數據庫意外的停機,在啟動之前它將會被重啟用以確保數據庫處於一致狀態。這也是MongoDB與傳統數據庫最接近的地方。
當然Journaling會輕微的影響到性能,大約5%。但是對於多數人來說額外帶來的安全性肯定是物有所值的。
總結:最好別關閉Journaling
默認情況下沒有身份認證MongoDB在默認設置下並沒有身份驗證。MongoDB會認為自身處在一個擁有防火牆的信任網絡。但是這不代表它不支持身份驗證,如果需要可以輕鬆的開啟
總結:MongoDB的安全性可以通過使用防火牆和綁定正確的接口來保證,當然也可以開啟身份驗證。
不可以對256G以上的Collection進行分片重新回到分片太遲的問題上來—— MongoDB不允許對增長到256G以上的Collection進行分片,之前版本的設置還沒有256G。這個限定在以後肯定會被移除,而這裡也沒有更好的解決方案。只能進行重編譯或者把大小控制在256G以下。
總結:在Collection達到256G以前進行分片。
與MongoDB通信的未經加密與MongoDB的連接默認情況下都是非加密的,這就意味你的數據可能被第三方記錄和使用。如果你的MongoDB是在自己的非廣域網下使用,那麼這種情況是不可能發生的。
然而如果你是通過公網訪問MongoDB的話,那麼你肯定會希望你的通信是經過加密的。公版的MongoDB是不支持SSL的。慶幸的是可以非常簡單的定制自己的版本。10gen的用戶則擁有特別定制的加密版本。幸運的是大部分的官方驅動都支持SSL,但是小麻煩同樣是不可避免的。點擊查看文檔
總結:當用公網連接時,要注意和MongoDB的通信是未加密的。
事務(重要關念)不像MySQL這些支持多行數據原子操作的傳統數據庫,MongoDB只支持單文件的原子性修改。解決這個問題的方法之一是在應用程序中使用異步提交的方式;另一個是:建立一個以上的數據存儲。雖然第一種方法並不適用於所有情況,但是很顯然比第二個來的要好。
總結:不支持對多文件事務。
消耗磁盤空間
這是我的第一個困惑:MongoDB會消耗太多的磁盤空間了。當然了,這與它的編碼方式有關,因為MongoDB會通過預分配大文件空間來避免磁盤碎片問題。它的工作方式是這樣的:在創建數據庫時,系統會創建一個名為[db name].0的文件,當該文件有一半以上被使用時,系統會再次創建一個名為[db name]. 1的文件,該文件的大小是方才的兩倍。這個情況會持續不斷的發生,因此256、512、1024、2048大小的文件會被寫到磁盤上。最後,再次創建文件時大小都將為2048Mb。如果存儲空間是項目的一個限制,那麼你必須要考慮這個情況。該問題有個商業解決方案,名字叫做TokuMX,使用後存儲消耗將會減少90%。此外,從長遠來看,repairDatabase與compact命令也會在一定程度上幫到你。



下節課程我們親手建立Mongo的執行環境與建立您的Mongo資料庫。


  • 安裝MongoDB

  1. 下載MongoDB
  2. 建立新資料夾給資料庫使用
  3. 執行Mongod指令
  4. 了解Mongod相關的引數

待續…







9 則留言: