您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)MongoDB是怎樣存儲數(shù)據(jù)的的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
前言
想要深入了解MongoDB如何存儲數(shù)據(jù)之前,有一個概念必須清楚,那就是Memeory-Mapped Files。
Memeory-Mapped Files
下圖展示了數(shù)據(jù)庫是如何跟底層系統(tǒng)打交道的。
內(nèi)存映射文件是OS通過mmap在內(nèi)存中創(chuàng)建一個數(shù)據(jù)文件,這樣就把文件映射到一個虛擬內(nèi)存的區(qū)域。
虛擬內(nèi)存對于進程來說,是一個物理內(nèi)存的抽象,尋址空間大小為2^64
操作系統(tǒng)通過mmap來把進程所需的所有數(shù)據(jù)映射到這個地址空間(紅線),然后再把當前需要處理的數(shù)據(jù)映射到物理內(nèi)存(灰線)
當進程訪問某個數(shù)據(jù)時,如果數(shù)據(jù)不在虛擬內(nèi)存里,觸發(fā)page fault,然后OS從硬盤里把數(shù)據(jù)加載進虛擬內(nèi)存和物理內(nèi)存
如果物理內(nèi)存滿了,觸發(fā)swap-out操作,這時有些數(shù)據(jù)就需要寫回磁盤,如果是純粹的內(nèi)存數(shù)據(jù),寫回swap分區(qū),如果不是就寫回磁盤。
MongoDB的存儲模型
有了內(nèi)存映射文件,要訪問的數(shù)據(jù)就好像都在內(nèi)存里面,簡單化了MongoDB訪問和修改數(shù)據(jù)的邏輯
MongoDB讀寫都只是和虛擬內(nèi)存打交道,剩下都交給OS打理
虛擬內(nèi)存大小=所有文件大小+其他一些開銷(連接,堆棧)
如果journal開啟,虛擬內(nèi)存大小差不多翻番
使用MMF的好處1:不用自己管理內(nèi)存和磁盤調(diào)度2:LRU策略3:重啟過程中,Cache依然在。
使用MMF的壞處1:RAM使用會受磁盤碎片的影響,高預(yù)讀也會影響2:無法自己優(yōu)化調(diào)度算法,只能使用LRU
磁盤上的文件是有extent構(gòu)成,分配集合空間的時候也是以extent為單位進行分配的
一個集合有一個或者多個etent
ns文件里面命名空間記錄指向那個集合的第一個extent
數(shù)據(jù)文件與空間分配
當創(chuàng)建數(shù)據(jù)庫時(其實MongoDB沒有顯式創(chuàng)建數(shù)據(jù)庫的方法,在向數(shù)據(jù)庫中的集合寫入數(shù)據(jù)時會自動創(chuàng)建該數(shù)據(jù)庫),MongoDB會在磁盤上分配一組數(shù)據(jù)文件,所有集合,索引和數(shù)據(jù)庫的其他元數(shù)據(jù)都保存在這些文件里。數(shù)據(jù)文件被放在啟動時指定的dbpath里,默認放入/data/db下面。典型的一個文件組織結(jié)構(gòu)如下:
$ cat /data/db $ ls -al -rw------- 1 root root 16777216 09-18 00:54 local.ns -rw------- 1 root root 67108864 09-18 00:54 local.0 -rw------- 1 root root 2146435072 09-18 00:55 local.1 -rw------- 1 root root 2146435072 09-18 00:56 local.2 -rw------- 1 root root 2146435072 09-18 00:57 local.3 -rw------- 1 root root 2146435072 09-18 00:58 local.4 -rw------- 1 root root 2146435072 09-18 00:59 local.5 -rw------- 1 root root 2146435072 09-18 01:01 local.6 -rw------- 1 root root 2146435072 09-18 01:02 local.7 -rw------- 1 root root 2146435072 09-18 01:03 local.8 -rw------- 1 root root 2146435072 09-18 01:04 local.9 -rw------- 1 root root 2146435072 09-18 01:05 local.10 -rw------- 1 root root 16777216 09-18 01:06 test.ns -rw------- 1 root root 67108864 09-18 01:06 test.0 -rw------- 1 root root 134217728 09-18 01:06 test.1 -rw------- 1 root root 268435456 09-18 01:06 test.2 -rw------- 1 root root 536870912 09-18 01:06 test.3 -rw------- 1 root root 1073741824 09-18 01:07 test.4 -rw------- 1 root root 2146435072 09-18 01:07 test.5 -rw------- 1 root root 2146435072 09-18 01:09 test.6 -rw------- 1 root root 2146435072 09-18 01:11 test.7 -rw------- 1 root root 2146435072 09-18 01:13 test.8 ... -rwxr-xr-x 1 root root 6 09-18 13:54 mongod.lock drwxr-xr-x 2 root root 4096 11-13 18:39 journal drwxr-xr-x 2 root root 4096 11-13 19:02 _tmp
mongod.lock中存儲了服務(wù)器的進程ID,是一個進程鎖定文件。數(shù)據(jù)文件是依據(jù)所屬的數(shù)據(jù)庫命名的。
test.ns是第一個生成的文件(ns擴展名就是namespace的意思),數(shù)據(jù)庫中的每個集合和索引都有自己的命名空間,每個命名空間的元數(shù)據(jù)都存放在這個文件里。默認情況下,.ns文件大小固定在16MB,大約可以存儲24000個命名空間。也就是說數(shù)據(jù)庫中的索引和集合總數(shù)不能超過24000,該值可以通過mongod的–nssize選項進行定制。
像test.0這樣以0開始的整數(shù)結(jié)尾的文件就是集合和索引數(shù)據(jù)文件。剛開始的時候,即使只有一條數(shù)據(jù),MongoDB也會預(yù)分配幾個文件,這種預(yù)分配的做法,能讓數(shù)據(jù)盡可能連續(xù)存儲,減少磁盤碎片。在像數(shù)據(jù)庫添加數(shù)據(jù)時,MongoDB會分配更多的數(shù)據(jù)文件。每個新數(shù)據(jù)文件的大小都是上一個已分配文件的兩倍(64M->128M->256M),直到預(yù)分配文件大小的上限2G。此處基于一個假設(shè),如果總數(shù)據(jù)大小呈恒定速率增長,應(yīng)該逐漸增加數(shù)據(jù)文件分配的空間。當然這個預(yù)分配策略也是可以通過–noprealloc關(guān)掉,但是不建議在production環(huán)境下使用。
默認的local數(shù)據(jù)庫,該數(shù)據(jù)庫不參與replication。當mongod是一個副本集的成員時,在local數(shù)據(jù)庫中就有一個叫做oplog.rs的預(yù)分配的capped集合,預(yù)分配的大小為磁盤空間的5%。這個大小可以通過–oplogSize進行調(diào)整。oplog主要用于副本集Primary和Secondary成員見的replication,它的大小限制了兩個副本集之間,在重新完全同步之前,允許多長時間不同步。
journal目錄,journal功能2.4版本默認是開啟的。
可以使用db.stats()
來確認已使用空間和已分配空間。
{ "db" : "test", "collections" : 37, "objects" : 317894523, #文檔總個數(shù) "avgObjSize" : 232.3416429039893, #單位是字節(jié) "dataSize" : 73860135744, #集合中所有數(shù)據(jù)實際大小(包括padding factor為每個文檔分配的額外空間以允許文檔增長)。該值在文檔size變小的時候,這個值不會減少,除非文檔被刪除,或者執(zhí)行compact或者repairDatabase操作 "storageSize" : 97834319392, #分配給集合的空間大小(包括為集合增長預(yù)留的額外空間和未分配的已刪除空間,即不會因為文檔size變小或者刪除而減小),實際上從數(shù)據(jù)文件中分配給集合的空間是以塊為單位,也稱之為extents,即分配的extents的大小 "numExtents" : 385, "indexes" : 86, "indexSize" : 58687466992, "fileSize" : 182380920832, #所有數(shù)據(jù)文件大小之和,不包括命名空間文件(ns文件) "nsSizeMB" : 16, "dataFileVersion" : { "major" : 4, "minor" : 5 }, "ok" : 1 }
使用db.accesslog.stats()
確認某個集合的使用量
{ "ns" : "test.accesslog", "count" : 145352932, "size" : 37060264352, #實際數(shù)據(jù)大小,不包括索引 "avgObjSize" : 254.967435758365, "storageSize" : 45794676448, #預(yù)分配的數(shù)據(jù)存儲空間 "numExtents" : 42, "nindexes" : 4, "lastExtentSize" : 2146426864, "paddingFactor" : 1, #當文檔因更新size增長時事先padding可以提速,減少碎片的產(chǎn)生 "systemFlags" : 1, "userFlags" : 0, "totalIndexSize" : 31897944512, "indexSizes" : { "_id_" : 6722168208, "action_1_time_1" : 8606482752, "gz_id_1_action_1_time_1" : 10753778336, "time_1" : 5815515216 }, "ok" : 1 }
感謝各位的閱讀!關(guān)于“MongoDB是怎樣存儲數(shù)據(jù)的”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。