Lyon's Blog
  • Home
  • Tags
  • Archives

MongoDB Storage Internals

我们都知道MongoDB通过 mmap 的方式将存储在磁盘上的数据文件映射到内存中进行操作,那MongoDB是如何组织数据文件的,最近在网上找了相关资源,在此做一个 翻译和汇总 , 非原创,原文在下面的参考链接部分。

我们按照从总体到内部的顺序进行分析,

Data Files

所有的 data files 存储在 dbpath 参考所指定的目录中,对应于每个数据库都有一个 、namespace file, 多个journal file 和 data file。

$ ls -lh /data/db
drwxr-xr-x 2 mongodb nogroup 4.0K Feb 14 13:14 journal
-rwxr-xr-x 1 mongodb nogroup    6 Feb 13 16:49 mongod.lock
-rw------- 1 mongodb nogroup  64M Feb 14 13:15 test.0
-rw------- 1 mongodb nogroup 128M Feb 14 13:14 test.1
-rw------- 1 mongodb nogroup  16M Feb 14 13:15 test.ns
drwxr-xr-x 2 mongodb nogroup 4.0K Feb 14 13:15 _tmp

mongod.lock 是MongoDB的lock 文件,可用来判断上次MongoDB是否正常shutdown。

其余的所有文件为 test 数据库的文件。

MongoDB 采用 aggressive pre-allocation的方式申请 data files,而且总会多申请一个备用的data file,如上面的test.1为备用的data file。数据文件会以指数级增长,最大为2GB。

namespace file 内存储了所有的 collection以及index。

data file 存储了所有的document及index。data file 以 extent为逻辑存储单元,每个data file包含多个extents.

Extents

每个extent被用来存储doucments或者index。

extents与data file之间的关系

extents and data file

extents与namespace file之间的关系

extents and namespace file

NOTE:

  • 一个extent只能存储一个collection的documents或index,不能同时用来存储documents和index。
  • 一个collection通常会有多个extents。
  • 当需要一个新的extent时会在当前data file中申请extent,如果当前data file空间不足,则申请新的data file.

同一个collection的所有extents通过指针连接,namespace file中的collection只需要指向其第一个extent即可。

extents

每个extent会存储一些metadata,其余空间存储records。

Records

每一个record会存储一些metadata及一个document。

records

record allocation

Indexes

MongoDB的索引是BTree结构,序列化到磁盘进行存储,存储在自己的extents中,而且每一个index有一个单独的namespace,并不属于其collection的namespace.

> db.system.namespaces.find()
{ "name" : "test.system.indexes" }
{ "name" : "test.foo.$_id_" }
{ "name" : "test.foo" }

Metrics from db.stats()

现在我们知道了MongoDB的数据组织方式,下面分析一下 db.stats() 的输出指标所代表的含义。

dataSize

data size

dataSize 是所有 documents 的大小总和,包括这个document的padding,也是所有records的总和, 当document被删除时dataSize会变小,但当减小document大小时,dataSize不会变化。

storageSize

storageSize

storageSize是所有extents的大小总和,会比dataSize要大,因为它会包括extents中未被使用的空间,以及因document被删除及移动带来的空闲空间。

当删除或减小document时,storageSize不会变化。

fileSize

fileSize

fileSize 包括所有的data extents, index extents以及data file中未使用的空间,是数据库存储在磁盘上的文件大小。会比storageSize要大,因为它还包括index extents,以及未使用的空间。

NOTE: dataSize 和 storageSize 都不包括index。

当删除数据库时,fileSize会变化,因为此数据库相应的data file会被删除,但当删除collection,documents及index时fileSize不会变化。

nsSize

namespace(test.ns)文件的大小。namespace file的大小是固定的,但可以通过修改nssize参数调整。

Fragmentation

当执行 update 及 remove 操作时会产生fragmentation.

fragmentation

如果文档的大小不固定,而且经常发生变化,则会产生大量的 fragmentation,这样会浪费内存及磁盘空间,增加Disk IO,而且由于update操作引起的文档移动还会导致索引的更新,使写操作变慢。可以通过比较 db.collection.stats() 输出中的 size 和 storageSize 来判断fragmentation的状况。

How to Combat

  • 定时执行 compact ,会lock数据库,要在secondary上执行。
  • 设定 collection schema, 使document不会增大
  • pre-pad documents, 使document不会增大。
  • 使用不同的collection, 尽量使用 db.collection.drop() 代替 db.collection.remove() 删除数据
  • 设置 usePowerOf2sizes 提高空间的重用度。

MongoDB Exorcises File Fragmentation Demons 介绍了 usePowerOf2sizes 所带来的空间利用率及性能的提升。不同的应用场景其效果也不一样。

参考

http://www.slideshare.net/mongodb/mongodb-london-2013understanding-mongodb-storage-for-performance-and-data-safety-by-christian-kvalheim-10gen

http://blog.mongolab.com/2014/01/how-big-is-your-mongodb/

http://linux.sys-con.com/node/2756958/mobile

Comments
comments powered by Disqus

  • « sftp in ssh config
  • MongoDB mmap »

Published

Feb 18, 2014

Tags

  • Disk 2
  • Fragmentation 1
  • MongoDB 8
  • Storage 1

Contact

  • Powered by Pelican. Theme: Elegant by Talha Mansoor