我在百X知道上回答問題時經常遇到類似與這樣的問題:MongoDB有沒有像MySQL一樣的ODBC驅動?MongoDB能不能像MySQL一樣獲取字段名稱或類型。
我的回答是:不行,因為MongoDB不是MySQL。這個回答顯得MongoDB太弱了,我的原意是你不能要求一個物理優秀教師幫你輔導數學,也許他能做到基本的教學,但他很難做到優秀數學教師那么全面。
今天討論的問題是:批量插入和批量查詢
昨天在百X知道上有人問起MongoDB的批量插入如何寫,這個我還真沒用過,一方面MongoDB的速度足夠快讓我從來沒有想過去找這種方法,另一方面MongoDB的官網以及API里也找不到這種方法。
那就帶來兩個問題。
問題1:這樣豈不是沒有速度更快的批量插入么?
這個問題毫無技術含量,MongoDB怎么可能會比MySQL慢?這里還是涉及到大家經常用到的傳統關系型數據庫和NoSQL的本質區別問題,NoSQL的每次操作都非常輕量級,小型化,除了數據的寫入外基本沒有多余的操作。再舉個栗子:MongoDB就是放東西(數據)時把東西扔入相應的櫃子(數據庫)即可,而MySQL則要保持與送東西人的溝通(雙向連接保持),東西的折疊整理分格存儲(事務+有模式)。MySQL的批量插入就是減少了溝通以及分格等過程,而MongoDB本身就不存在這些過程,因此MongoDB就不存在批量插入這個概念了。結論就是,MongoDB的普通插入比MySQL的批量插入還要快,或者說MongoDB的普通插入就是批量插入。
問題2:把多個操作放入一個事務里一起執行不就不能實現了?
這個問題更沒有技術含量了,MongoDB有事務么?還是那句,不要把NoSQL當關系型數據庫用。那豈不是MongoDB的數據完整性和數據安全性會很差?這個,還得再重復一遍,MongoDB的設計是為了處理大規模數據的,所以對數據完整性要求不是那么嚴格。如果非要較真兒的話,MongoDB也可以處理這種情況,就是getLastError,它會犧牲性能以獲取數據操作是否正確,你可以在批量插入一批數據后調用一次這個方法,如果出錯,就把這批數據重新操作一遍,一批調用getLastError一次,既可保證性能,又可保證數據安全。
批量查詢
再來說一下批量查詢,這里的批量對應於官網上的batch select的概念,可以理解為一次查詢一批數據。很多人在使用數據庫的時候會用:
Statement stmt = a.createStatement();
ResultSet rs = stmt.executeQuery(sql);
for(int i = 1; i < 10000; i++){
//read data from rs
}
這樣操作,會把數據庫中的數據全部讀入內存還是每條數據都去數據庫中讀一次?實際上兩者都不是,MySQL會把部分數據放入內存,如果這部分數據讀完了,那么再讀入一部分。因為很久沒用MySQL了,我記得C++的驅動中確實有一個類是用於把全部數據都讀入內存的,不過這種方法很少人使用。
MongoDB的查詢是這樣的,你用Cursur去查詢,如果沒有設置batch size這個參數,那么MongoDB默認會返回101條數據,等到這101條數據讀完了,也就是說用戶想讀第102條數據,那么驅動會再次去MongoDB中獲取后面的一批數據,這批數據不是以個數記的,而是最大限制4M的大小,將這4M的數據返回供用戶繼續讀,讀完再申請4M。當然,你可以通過batch size來改變這一數值,如果設置了,那么每次返回都會返回batch size條數據。
轉載請注明出處:http://blog.sina.com.cn/s/blog_56545fd301013zav.html