mongodb获取空闲磁盘空间
这篇文章 mongodb使用内存和硬盘特性 我们介绍过mongodb删除数据后,并不会释放磁盘空间。大部分数据库为了性能都会这样做,比如mysql也是。不过mysql可以整理磁盘空间,把空闲的磁盘释放掉,还给操作系统,但是mongodb却不会。虽然说mongodb也有整理磁盘的接口调用(compact),但是它并不是释放所有的空闲空间,只是把很少的部分空间释放,继续可以忽略不计。并且compact时会锁表,导致数据库暂时不可用,也要谨慎使用。
如果磁盘空间不可以释放,如何维护mongodb的长时间稳定运行呢?实际上我们不需要mongodb把磁盘还给系统,只需要mongodb占用的磁盘大小一直维持在一个范围内即可(比如500G)。相当于mongodb一开始就划分了这么大的空间,后续不再增长,达到限额就把旧的数据覆盖即可。
要想实现mongodb对磁盘的占用维持在一个稳定的范围,定期删除数据是不可避免的。问题在与什么时候删除,删除多少数据呢?我们就需要知道当前mongodb到底占用了多少。虽然分配了500G,但是只占用了100G,所以不需要删除;如果占用空间快到500G了,我们就需要删除部分数据,因为超过500G后,mongodb就会分配新的磁盘,并且无法释放(除非导出数据库再导入)。
存储状态查询
mongodb官方提供了查看数据库或者集合状态的方法
db.stats()
db.xxx.stats()
db | collections | views | objects | avgObjSize | dataSize | storageSize | indexes | indexSize | totalSize | scaleFactor | fsUsedSize | fsTotalSize | ok |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
xxx | 152 | 0 | 256646 | 4953.99530481675 | 1271423079 | 477196288 | 308 | 14938112 | 492134400 | 1 | 1222409334784 | 1897374105600 | 1 |
ns | size | count | avgObjSize | numOrphanDocs | storageSize | freeStorageSize | capped | wiredTiger | nindexes | indexBuilds | totalIndexSize | totalSize | indexSizes | scaleFactor | ok |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
xxx | 215551960 | 6478 | 33274 | 0 | 59797504 | 1327104 | false | (Document) 15 Fields | 2 | (Array) 0 Elements | 286720 | 60084224 | (Document) 2 Fields | 1 | 1 |
每个表示大小的单位取决于scaleFactor,基础都是字节,scaleFactor就是获取的字节数除以几,为了方便统计MB或者GB
-
db 数据库名
-
collections 数据库有多少集合
-
views 数据库有多少视图
-
objects 数据库有多少条数据
-
avgObjSize 每条就平均大小(字节)
-
dataSize 数据大小(字节),注意并不是磁盘占用大小,因为有压缩
-
storageSize 磁盘占用大小(数据)(字节)
-
indexes 索引数量
-
indexSize 索引磁盘占用大小(字节)
-
totalSize 全部磁盘占用大小(字节)(索引加数据)
-
scaleFactor 上面统计字节数再相除的除数,主要用作如果不想统计字节,可以设置为1024,就会自动除以1024,变成K,MB GB依此类推
-
fsUsedSize mongo占用的总的空间大小。不仅仅是数据库,包括mongo自身的bin文件和日志等
-
fsTotalSize mongo申请的总的磁盘大小。上面的只是用的到,有的磁盘空间已经申请了,但是还没用。
-
ns 集合名
-
size 记录在内存中未压缩的数据占用空间
-
count 数据条数
-
freeStorageSize 分配了磁盘空间,但是还未使用的大小(字节)
-
totalIndexSize 索引占用的大小(字节)
空闲状态查询
上面只是展示了占用了多少磁盘空间,mongodb提供的这两个查看数据库或者集合状态的api,可以传递参数,获取空闲可用的空间大小。
db.runCommand(
{
dbStats: 1,
freeStorage: 1
}
)
db | collections | views | objects | avgObjSize | dataSize | storageSize | freeStorageSize | indexes | indexSize | indexFreeStorageSize | totalSize | totalFreeStorageSize | scaleFactor | fsUsedSize | fsTotalSize | ok |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
xxx | 152 | 0 | 2498923 | 916.97596161542 | 978820957 | 477196288 | 241803264 | 308 | 14921728 | 4743168 | 492118016 | 246546432 | 1 | 1222521229312 | 1897374105600 | 1 |
我们看到多了freeStorageSize indexFreeStorageSize totalFreeStorageSize,我们增加删除一下数据,看一下变化。
db | collections | views | objects | avgObjSize | dataSize | storageSize | freeStorageSize | indexes | indexSize | indexFreeStorageSize | totalSize | totalFreeStorageSize | scaleFactor | fsUsedSize | fsTotalSize | ok |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
xxx | 152 | 0 | 249892 | 3916.97596161542 | 978820957 | 477196288 | 241803264 | 308 | 14921728 | 4743168 | 492118016 | 246546432 | 1 | 1222521229312 | 1897374105600 | 1 |
xxx | 152 | 0 | 249962 | 3918.08719725398 | 979372912 | 477196288 | 241803264 | 308 | 14921728 | 4743168 | 492118016 | 246546432 | 1 | 1222543265792 | 1897374105600 | 1 |
xxx | 152 | 0 | 249968 | 3917.99706762466 | 979373891 | 477196288 | 241688576 | 308 | 14921728 | 4734976 | 492118016 | 246423552 | 1 | 1222545735680 | 1897374105600 | 1 |
xxx | 152 | 0 | 247958 | 3747.61018398277 | 929249926 | 477196288 | 241688576 | 308 | 14938112 | 4743168 | 492134400 | 246431744 | 1 | 1222549508096 | 1897374105600 | 1 |
xxx | 152 | 0 | 247961 | 3747.56663749541 | 929250371 | 477196288 | 254107648 | 308 | 14921728 | 4784128 | 492118016 | 258891776 | 1 | 1222551937024 | 1897374105600 | 1 |
第1条是原始数据状态,第2条是增加了部分数据后直接查询的状态,我们看到objects增加了,从249892增加到249962,但是freeStorageSize并没有变,这是因为mongodb写入数据或者同步信息有延迟,这是正常的。又插入了几条数据,第3条再查询,就看到数据更新了,freeStorageSize indexFreeStorageSize totalFreeStorageSize都有增加。4和5是对数据删除,可以看到freeStorageSize indexFreeStorageSize totalFreeStorageSize也都有相应减少。
storageSize始终没有变换,就是因为mongodb还有空闲可用的空间,插入的时候也不会增加,删除也不会释放。
https://www.mongodb.com/docs/manual/faq/storage/#faq-disk-size
https://www.mongodb.com/docs/manual/reference/command/dbStats/#mongodb-dbcommand-dbcmd.dbStats
https://www.mongodb.com/docs/manual/reference/method/db.stats/
https://www.mongodb.com/docs/manual/reference/command/collStats/#mongodb-dbcommand-dbcmd.collStats
https://www.mongodb.com/docs/manual/reference/method/db.collection.stats/#mongodb-method-db.collection.stats
MongoServerError: scale has to be a number > 0
如果我们使用db.stats({scale: 1, freeStorage: 1})就会报上面的错误,按照官方的描述,好像这个实现还有问题。因为db.stats()是对db.runCommand({dbStats: 1})的封装,可能部分功能还没有实现,所以只能使用runCommand。