2012-06-25 56 views
6

我收集了包含域信息的文檔domain。其中一部分是歷史whois記錄,可能爲零或更多,並佔據了文檔的大部分空間。MongoDB:保存文檔是否重寫整個文檔?

如果我加載整個文檔,改變一些小的(如更新數字字段),並使用save()方法將mongo刷新整個文檔到磁盤或只更新已更改的BSON?最終我的問題是,如果我爲了節省I/O而使用update()複雜化了代碼,還是應該使用save()

這不完全是由於懶惰,文檔(在完整閱讀後)會經歷一系列步驟來修改/處理文檔,並且如果有任何更改,整個文檔都會被保存。但是,如果保存文檔的成本很高,那麼我可能需要以不同的方式考慮...

回答

4

您可以使用$set更新文檔中的單個字段。這將修改磁盤上的字段。但是,if the document grows beyond the size before the update, the document may have to be relocated on disk

同時,here is what the documentation says about save versus update

>// x is some JSON style object 
>db.mycollection.save(x); // updates if exists; inserts if new 
> 
>// equivalent to: 
>db.mycollection.update({ _id: x._id }, x, /*upsert*/ true); 

參考

+0

這很有幫助,但它並沒有真正回答我的問題。如果我有一個10MB BSON文檔,我讀它改變一個屬性並保存它會再次寫滿10mb?假設文件不必重新定位。 –

+0

關於*「的詳細信息是整個事情寫的」*取決於MongoDB使用內存映射文件的事實。如果只更新一個屬性,理想情況下只有那些字節被刷新到磁盤。但是,如果BSON發生了足夠的變化,那麼您最終可能會將整個事件刷新到磁盤。 –

+1

@蓋茨VP:我認爲整個頁面被標記爲髒,必須刷新。 –

2

這取決於您正在使用的客戶端庫。例如,Mongoid(紅寶石中的ODM)足夠智能,只能發送已更改的字段(使用$set命令)。它有時太聰明瞭,並且沒有捕捉到我對嵌套哈希所做的更改。但我從來沒有見過它發送不變的領域。

其他庫/驅動程序可能會有不同的表現。

0

我知道這個問題很舊,但知道它是如何工作來幫助您設計數據庫結構非常有用。以下是有關MongoDB存儲引擎的詳細信息: https://docs.mongodb.com/v3.2/faq/storage/

該文檔回答了問題。基本上,如果你更新MongoDB中的整數字段,它將標記整數駐留在內存中的頁面(通常爲4k)爲髒,並且會在下一次磁盤刷新時將內存頁面寫入磁盤。所以,如果你的文檔大小非常大,那麼它很可能只會將文檔的一部分寫入磁盤。

但是,還有很多其他情況。如果您將更多數據填充到文檔中,MongoDB有可能需要將整個文檔移動到新位置才能使文檔增長。在這種情況下,整個文檔將被寫入磁盤。

相關問題