在现实的世界中,任何事情都有两面性,在程序的世界中,亦然! 我们不论是在使用一门新的语言,还是一门新的技术,在了解它有多么的让人兴奋,让人轻松,多么的优秀之余,还是很有必要了解一些他的局限性,方便你在实际开发过程中 遇到这些的时候 明白应该怎么处理,在涉及到这些地方的时候,能预先的判断,文章翻译自Mongo DB 官网,翻译的不好,还望大家谅解,同时本人也在使用Mongo DB 对空间地理编码进行一些操作, 希望大家多多交流 多多指教,在此先行谢过!!!
该笔记提供了一些关于使用Mongo DB时,对软硬件的一些限定(MongoDB本身的限制)
翻译至: http://docs.mongodb.org/manual/reference/limits/#shard-key-limitations
BSON 文件大小限制
1.BSON文件的最大限制为 单个文档不超过16MB。
最大文件大小的限制有助于确保单个文件不会过多的占用内存,在传输过程中,不会占用过多的宽带。当需要存储到MongoDB中的单个文件大小超过了Mongo DB限制的最大文件大小时,MongoDB 提供了另外一套API—Grid FS 。
2.深度嵌套BSON 文档
自Mongo DB 2.2版本更新之后, MongoDB 支持单个文件不超过100的BSON文件嵌套。
命名空间
命名空间的长度:在每一个命名空间中,包括数据库名,集合名称在内,不得超过123KB。
命名空间数量的限制:命名空间数量的限制 为命名空间的大小除以628. 例如:一个16mb的命名空间能提供约24,000个命名空间, 单个的集合名称或者索引名称均为一个命名空 间。
命名空间的文件大小: 命名空间的文件不能超过2047MB. 默认的命名空间大小为16MB,不过你可以通过nsSize 参数来配置命名空间的大小。
在创建数据库时,系统会创建一个名为[db name].0的文件,当该文件有一半以上被使用时,系统会再次创建一个名为[db name].1的文件,该文件的大小是方才的两倍。这个情况会持续不断的发生,因此256、512、1024、2048大小的文件会被写到磁盘上。最后,再次创建文件时大小都将为2048Mb。如果存储空间是项目的一个限制,那么你必须要考虑这个情况。
索 引
1.索引键的限制 2.6版本更新对比
索引项的总大小(包括索引结构),取决于使用的数据类型(见下图--BSON Type),但必须小于1024KB.
MongoDB 2.6版本更新后,MongoDB 对索引键的创建进行了很强的限制,具体限制内容如下:
a.如果集合的索引数目已经达到最大限制,Mongo DB 不会再为其创建索引项。在2.6 之前,MongoDB会为其创建索引,但不会再去索引这些文档。
b.如果对索引条目超过索引键限制的字段重建索引则会出现错误。重建索引的操作会出现在以下情况:执行compact 和 repairDatabase 命令时,调用 db.collection.reIndex()方法时. 因为这些操作会删除掉集合中现有的所有已建索引,然后尝试重新创建索引,但索引键限制(出现的)错误会阻止对集合做任何的索引重建操作。但在使用repairDatabase命令的情况下,程序会继续往下执行。
c.对于已经存在索引超过索引键限制的集合,MongoDB不会再插入任何创建过索引的文档。相反,会提示一个错误。2.6之前,MongoDB会插入带有索引的文档,但是不会对插入的文档进行索引操作。
d.在更新索引的过程中,如果更新的索引值引发了索引超过索引键限制(的错误),则会返回一个错误信息。
e.如果一个文档中包含了 超过索引键限制的片键,对于该文件的任何更新,移动,都会出现错误。
If an existing document contains an indexed field whose index entry exceeds the limit, any update that results in the relocation of that document on disk will error.
f.mongorestore 和 mongoimport 不会对任何出现索引超过索引键限制的的集合插入新的文档。
g.在 2.6版本中,如果索引超过了索引限制数目,在进行集成的初始同步时,二级副本集成员会继续执行文件复制操作,但是会在日志中打印警告信息。
如果副本集中的MongoDB 不是同一个版本,主级版本为2.4,副级版本为2.6,副级会按照2.4的版本将已经插入或更新的文件复制到主服务器。但是,如果文档中存在所建索引项超过索引创建限制的文档,MongoDB会将错误信息打印到日志文件中.
h.对于现有的分片集合,如果数据块有一个文档,其中包含一个片键的索引条目超过索引键限制。执行 chunk migration (块迁移)时会失败。
2.每个集合的索引个数:每个集合可以创建(不超过)64个索引.
3.索引名称长度: 完全限定名(包括名称和点分隔符,例如databse.collection.indexName)不超过128个字符。
4.复合索引的片键:在创建复合索引时,复合索引中的字段不得超过31个。
5.查询时,不能同时使用文本索引和地理空间索引:在进行一个查询操作时,需要一个不同类型的特殊索引,你不能混合的使用 text命令来执行特殊的文本索引(text index)。 比如,你不能同时使用 text 和 $near 命令来进行查询 ($near 用于地理编码中的空间查询,text 用于一般的文本检索)
数 据
集合的最大文档数上限
Mongo DB 2.4版本后, 如果你使用max参数来设定允许在集合中创建的最大文档数,则文档的最大限制数必须保证在2的32次方之内;如果创建集合时没有指定最大文档个数,那么可以创建的文档个数是不受限制的。
数据大小
单个mongod实例不能管理一个数据集超过操作系统提供的最大虚拟内存地址空间。
数据库中集合的数量
数据库中集合的的最大数量是由命名空间文件的大小和集合中的索引数量决定的。 更多详细信息请回看 命名空间 .
副 本 集
副本集中的成员数量: 一个副本集中最多能包含12个成员(节点),如果你的应用中集群的节点有12个以上,你就应该考虑使用主重复制了。
在副本集中能参与选举的成员数量: 在副本集中,只有7个成员能在任意特定时间内具有选举的权利,更多信息请参见--副本集选举
自动创建的操作日志的最大值: 在2.6版本后,如果你没有明确的指定操作日志的大小(比如 通过设置oplogSizeMB 或者--oplogSize),MongoDB 会自动创建一个不超过50GB的操作日志。
分 片 集 群
这里仅仅只提供分片集群的限制和阀值
分片操作限制
在分片环境下,不可以使用的操作:
1.在分片中, group 是无法使用的, 你应该用mapReduce 或者 aggregate 代替 group.
2.db.eval()在分片集合中是无法兼容的,你可能只有在分片集群中尚未进行分片的集合中使用db.eval().
3.$where 函数将不允许引用DB的对象,这在非分片的集合中是罕见的。
4.$isolated 在分片集群环境下更新修改器是不起效的。
5.$snapshot 在该环境下失效。
6.geoSearch命令也不支持分片。
分片集群中的覆盖查询:MongoDB中不支持在分片集合中进行覆盖查询。
现有(分片)集合的数据大小:
对于现有存在的集合,MongoDB支持对不大于256GB的文件集合进行分片。根据文件大小的分布,MongoDB最多能对高达400GB的集合文件进行分片。
MongoDB能精确的限制块的大小和数据的大小
重要提示:当成功进行分片后,分片集合本身会占用一定的空间。
分片集合中的单文档修改
在分片集合中进行的所有update()和remove()操作,必须明确的指定 justOne 或者 multi:false ,并且必须在查询参数中包含有 片键(shard key) 或 _id 字段(mongodb 自带的唯一标识符) 。 如果update() 和 remove()操作指定了 justOne 或者multi:false 但并未指定 片键(shard key)或者 _id 字段,那么将返回一个错误信息。 注:片键(shard key )可以包含集合中的多个字段(field)
分片集合中的唯一索引键
MongoDB不支持通过分片创建唯一索引键,除非该唯一索引键以完整的分片字段作为索引的前缀,在这种情况下,MongoDB会通过这个完整的字段强制创建一个唯一索引,而不再是对单一的一个字段创建索引。
参考:Enforce Unique Keys for Sharded Collections查看另外一种实现方式。
片键的限制
片键的大小限制: 片键的总长度不得超过512bytes.
片键的类型: 片键的类型可以是一个升序排列的索引 也可以是一个片键开头并指定排列顺序的复合索引 或者散列索引。
片键的索引不能被指定为下列类型的索引:multikey index , text index ,geospatial index.
片键是不可变的
在已经完成的分片集合中,不能再修改片键,如果必须要修改:
1. 将MongoDB中的所有数据转成成其他格式
2.删除掉之前的分片集合。
3.通过配置让分片使用新的(需要修改成的)片键;
4.预划分片键的范围,确保能在初始化的时候能均匀分布
5.还原之前的数据到MongoDB.
文档中 片键的值是不可变的
在成功的向已分片的集合中新增一个文档后,你不能修改这个文档中被用于创建索引的字段的值, update()操作也不会再更新这个文档中被用于创建索引的字段的值。
递增的片键能有效的限制插入的吞吐量
对于新增操作量很大的集群,递增的片键能很好的有效的限制插入的吞吐量。如果你的片键是_id,你需要注意的是 ObjectId类型的_id,其值通常是自增的。
通过递增索引来插入文档,所有插入的文档都属于同一个分片中的块,系统最终会接收所有的写入操作并合理的将写入的内容分配到不同的块中,目的是为平均的分配数据。 然而,在任何时候集群会直接将新增文档插入到一个分片中,这就造成了插入时吞吐量的瓶颈。
如果集群主要负责读取和更新操作,那么这种限制并不影响集群。
为了避免这种约束,可以使用散列片键或者选择一个非自增或者减少自增的字段(select a field that does not increase or decrease monotonically.)。
在2.4的版本中:散列片键和散列索引 按照值的顺序排列来存储起索引键。
操 作
存储文档
如果排序操作所使用的内存不到32MB,那么MongoDB 将只返回没有片键的排序结果
聚合管道操作
在2.6的版本更新中,管道阶段将对内存有一个100MB的限制,如果该段超过了这个限制,MongoDB会产生一个错误,为了允许处理大数据集,可以使用 allowDiskUse参数来确保在聚合管道阶段能将数据写入临时文件。 请参见$sort and Memory Restrictions and $group Operator and Memory.
使用 2d进行空间查询时,不能使用 $or 操作符,请参见$or and 2d Index Internals.
球面多边形必须适合半球操作
任何使用GeoJSON中的$geoIntersects 或 $geoWithin进行几何查询时,必须适合半球。MongoDB在解析几何图形时,超过一半的球体将作为互补的较小的几何图形来进行的查询。
写入命令操作的 限制大小
写入命令能接收不超过1000个的操作。mongo脚本中的Bulk()及类似的方法则对此没有限制。
命名的限制
数据库名严格区分大小写:MongoDB 不允许仅通字母的大小写来却分数据库的名称。例如test和Test
Window操作系统中数据库名称的限制(2.2版本中更新):
如果MongoDB的开发环境在Windows系统下,MongoDB不允许在数据库的名字中出现以下字符:/\. "*<>:|?
同时,数据库名不能包含空字符
Unix/Linux系统下命名的限制
如果MongoDB的开发环境在Windows系统下,MongoDB不允许在数据库的名字中出现以下字符: /\. "
同时,数据库名不能包含空字符
数据库名称的长度限制:数据库名称不能为空且必须控制在64个字符范围内。
集合名称的限制(2.2版本中更新):
集合的名称应该以下划线或者字母开头,并且名称中不能包含: $ , 空字符串(空格), 空字符(null character),不能以system作为前缀。在mongo脚本中,使用db.getCollection()来指定集合名称可能会和脚本冲突,或者被当做不被验证通过的JAVAScript.
字段名称的限制:字段名称中不能包含" . ","$" , 或者 空字符(null character) 参见 Dollar Sign Operator Escaping 查阅另一种方式。