2013-10-09 29 views
2

通過mongod啓動Mongo後,我運行了一個Mongo查詢,花費了秒。在我的「管理員」數據庫上調用db.serverStatus()顯示Mongo具有1GB的resident內存。文檔解釋了「常駐」內存是Mongo使用的物理磁盤/ RAM的數量。Mongo服務器狀態 - 「Resident」內存

然後,我重新運行相同的查詢,但它花了秒。這次看內存resident,我看到了5 GB。

我相信,RAM的大幅增加有助於解釋爲什麼查詢時間縮短了300到8秒,但爲什麼常駐內存跳得這麼快?

是否有某種類型的「暖」步驟建議準備Mongo以避免300秒查詢?

回答

4

原因在於MongoDB使用操作系統的mmap功能。這意味着,至少在Linux系統上,mongodb的內存處理基於操作系統的一些稱爲內存映射文件的功能。 Linux系統中的內存在幾個層次上進行尋址,基本上任何程序都會在64位系統128TB上的32位系統上看到2GB的地址空間。這是一個虛擬地址空間,這意味着在32/64位上可以用4kb內存頁尋址內存量(頁面是內存中單獨處理的部分)。這就是爲什麼如果你在一個32位的系統上啓動mongoDB,它會引發一個警告,這個系統上的數據庫只能處理2GB的數據。顯然,這個虛擬地址空間大於物理內存的數量,因此這些虛擬地址與物理地址之間存在映射關係。一些虛擬地址駐留在真實的物理內存中,因此它們處於真實的內存中,但確保這一點的算法在內核一側。運行在Linux系統上的程序只能處理虛擬地址,如果試圖訪問不在物理內存中的虛擬內存地址,就會發生頁面錯誤(您可以在serverStatus命令的額外信息字段上跟蹤此地址)。 (你可以在這裏找到簡短的解釋here

如果虛擬地址駐留在物理內存中的速度與內存速度一樣,那麼訪問內存時,訪問當前沒有物理內存的虛擬地址意味着從磁盤到內存的分頁以及快速讀取內存,隨機讀取磁盤。 (這使得不同的你的情況)

有MongoDB中的命令與您可以實施一個集合或該命令是touch 索引緩存如果您使用此命令之前,將數據加載到內存中第一個查詢,你會在第一次嘗試8秒後得到結果。不幸的是,你不能真正強制操作系統將這些數據保存在內存中,所以如果你有其他的東西,內存操作系統會在一段時間內將這些數據分頁。

如果你有足夠的物理內存mongoDB將保留所有的數據和索引在內存中。這並不總是需要的。有一部分數據需要在內存中以避免大量的頁面錯誤,這是workingset。您可以使用db.runCommand({ serverStatus: 1, workingSet: 1 })命令檢查工作集的大小。

在操作系統級別,你不能處理分頁,但是如果你有足夠的內存,內核通常會盡可能地保留緩存的內容。如果工作集適合內存,你或多或少就可以。如果某些文檔很少被訪問,並且沒有足夠的內存來保存所有內容,則無論如何都會將其分頁。

當你運行一個查詢時,可能發生幾件事情。索引可以涵蓋哪些手段根本不會觸及任何文檔,如果您的查詢在某些概念中有選擇性,則只會觸及索引的一部分。不幸的是,定義內存真的很難,並且唯一可以做的就是監視(工作集指標是一種估計)。內存不足的症狀可以通過檢查presentation來確定。並使用MMS

+0

感謝您的有用答案。因此,如果我在內存中擁有足夠的內存以僅覆蓋索引,那麼在從找到的文檔中獲取非索引字段時仍然可能發生頁面錯誤? –

+0

該問題有幾個級別。你可以檢查工作集的大小,我很快更新我的答案。 – attish

+0

我更新了工作集相關部分。我很高興,那可以幫助你。 – attish