MongoDB 学习笔记
最近尝试在项目中使用 MongoDB,遇到不少问题。关于 MongoDB 的基本安装和使用就不写了,另外一些问题记录如下(以下问题基于 MongoDB 1.8.2):
1、关于 MongoDB 中最多可以使用多少个集合
我首先遇到的是大量的数据是保存在一个集合中还是分别保存在多个集合中,如果选择后者的话,MongoDB 最多可以支持多少个集合呢?
官方网站有关于这个问题的说明(Using a Large Number of Collections)。默认情况下,MongoDB 的每个数据库的命名空间保存在一个 16MB 的 .ns 文件中,平均每个命名占用约 628 字节,也即整个数据库的命名空间的上限约为 24000。
每一个集合、索引都将占用一个命名空间。所以,如果每个集合有一个索引(比如默认的 _id 索引),那么最多可以创建 12000 个集合。如果索引数更多,则可创建的集合数就更少了。同时,如果集合数太多,一些操作也会变慢。
不过,如果真的需要建立更多的集合的话,MongoDB 也是支持的,只需要在启动时加上“--nssize”参数,这样对应数据库的命名空间文件就可以变得更大以便保存更多的命名。这个命名空间文件(.ns 文件)最大可以为 2G,也就是说最大可以支持约 340 万个命名,如果每个集合有一个索引的话,最多可创建约 170 万个集合。
还需要注意,--nssize 只设置新创建的 .ns 文件的大小,如果想改变已经存在的数据库的命名空间,在使用这个参数启动后,还需要运行 db.repairDatabase() 命令来调整尺寸。
2、关于分片
MongoDB 支持自动分片,这给维护带来很大的便利。不过,使用自动分片时也需要足够小心,不然可能会带来很严重的效率问题。
比如,如果某个集合保存的是日志记录,最常用的查询是根据时间段来批量查询日志,这样的情况下,将这个集合按 _id 分片就是不合适的,因为这样将把日志近似随机地分到各个片上,输入一个查询时间段时,MongoDB 必须在所有的片上进行检索,并在所有的片都返回结果后才能汇总。一个经验原则是分片时让每次查询所要检索的片的数量尽量少一些,比如对于这个需求来说,按时间分片可能就更合适一些(当然,只按时间分片会带来另一个问题:所有的写操作可能会集中在最新的块(chunk)上。所以实践中,可能要使用组合键进行分片)。
自动分片虽然方便,但使用之前还是要先仔细分析可能的需求,因为一旦开始某种自动分片,之后想再修改就麻烦了。官方文档中提到,一旦以某个键建立了分片,暂时没有再修改为按其它键分片的办法,如果真的需要修改,只能先将这个分片删除,再重建一个。同时,已经分片的集合将不能重命名,如果真的需要重命名,最快捷的办法是用新名字再建一个集合,然后将数据从老集合中导入进来。
3、关于数据压缩
MongoDB 的开发团队认为硬盘很便宜,并且将越来越便宜,因此 MongoDB 不会自动压缩数据文件的占用空间(因为这通常比较慢)。如果要手动压缩数据库文件,使用 db.repaireDatabase()
命令即可,这儿有一个详细的例子。
需要注意的是,repaireDatabase 操作需要你的硬盘有足够的剩余空间(不能小于现有的数据文件的大小),否则会报错。所以,repaireDatabase 操作得趁早做(比如数据文件占用的空间还没有超过你的硬盘大小的一半的时候),否则就比较麻烦了,要么将数据文件拷到另一块大硬盘上操作,要么将数据文件导出再导入,要么挂载一个大硬盘到数据库目录下的 _tmp 文件夹下,这儿和这儿有一些讨论。
评论: