上限集合(Capped Collections)是固定大小的集合,支持插入以及根据插入顺序检索文档的高吞吐量操作。上限集合的工作方式类似于循环缓冲区:一旦集合填满了其分配的空间,它就会通过覆盖集合中最旧的文档为新文档腾出空间。
有关创建上限集合的更多消息,可以参见createCollection()或create
作为上限集合的替代方式,可以考虑MongoDB的TTL (Time To Live)索引。像Expire Data from Collections by Setting TTL中描述的,这些索引使你可以基于日期类型字段的值和索引的TTL值来过期并从常规集合中删除数据。
TTL索引与上限集合不兼容
特性
-
插入顺序:上限集合可以确保保留插入顺序。因此,查询不需要索引即可按插入顺序返回文档。没有这些索引开销,上限集合可以支持更高的插入吞吐量。
-
自动删除最旧的文件:为了给新文档腾出空间,上限集合在填满空间后会自动删除集合中最旧的文档,无需脚本或显式删除操作。
以下是一些使用上限集合的潜在用例:
- 存储大容量系统生成的日志信息。在没有索引的情况下将文档插入上限集合接近于将日志信息直接写入文件系统的速度。此外,内置的先入先出属性可在管理存储使用的同时维护事件的顺序。
- 在上限集合中缓存少量数据。因为缓存大多数都是读操作而不是写,你可能需要确保集合始终保留在工作集(即RAM)中或者为需要的一个或多个索引接受一些写操作。
比如,将副本集中存储操作日志的
oplog.rs集合使用上限集合。从MongoDB 4.0开始,与其他上限集合不同,oplog可以超出其配置的大小限制,以避免删除主要提交点。 -
_id索引:上限集合默认具有
_id字段和_id字段索引。
限制和建议
- 更新:如果计划更新上限集合中的文档,可以创建索引以免更新操作扫描整个集合。
- 文档大小:在3.2版本中修改。如果更新或替换操作修改了文档大小,则该操作将失败。
- 文档删除:上限集合中不能删除文档。要从集合中删除所有文档,可以使用
drop()函数删除集合并重新创建该上限集合。 - 分片(Sharding):上限集合不能分片。
- 查询效率:使用自然顺序可以有效的从集合中检索最近插入的元素。这有点类似于日志文件上的
tail。 $out聚合:聚合管道$out阶段无法将结果写入上限集合。- 事务(Transactions):从MongoDB 4.2开始,上限集合事务无法进行写操作,但是仍然支持上限集合事务读操作。
上限集合使用
-
创建上限集合:必须使用
db.createCollection()函数显式创建上限集合,该方法是mongoshell中create命令的帮助器。创建上限集合必须指定该集合的最大大小(以字节为单位),MongoDB将会为该集合预先分配大小。上限集合的大小包括少量内部开销空间:db.createCollection( "log", { capped: true, size: 100000 } )如果
size<=4096,则集合的上限为4096字节;否则,MongoDB将提高提供的大小,使其成为256的整数倍。此外,还可以使用
max字段为集合指定最大文档数,如下所示:db.createCollection("log", { capped : true, size : 5242880, max : 5000 } )注意:
无论是否指定最大文档数
max,都需要size参数。如果集合在达到最大文档数之前达到最大大小限制,MongoDB将删除较旧的文档。 -
查询上限集合:如果在没有指定顺序的上限集合上执行
find(),则MongoDB保证结果的顺序与插入顺序相同。如果以相反的插入顺序检索文档,可以在find()函数之后加上$natural为-1的sort()函数。db.cappedCollection.find().sort( { $natural: -1 } ) -
检测集合是否有上限:可以使用
isCapped()函数检测集合是否有上限。db.collection.isCapped() -
将集合转换为上限集合:可以使用
convertToCapped命令将非上限集合转换为上限集合:db.runCommand({"convertToCapped": "mycoll", size: 100000});size参数指定上限集合的大小(以字节为单位)。在操作期间它将持有数据库排他锁。锁定统一数据库的其他操作将会被阻塞,直到该操作完成。可以查看What locks are taken by some common client了解锁定数据库的操作。
-
尾光标(Tailable Cursor):可以将尾光标与上限集合一起使用。与Unix
tail -f命令类似,尾光标跟踪上限集合的尾部。将新文档插入上限集合后,可以使用尾光标继续检索文档。可以查看Tailable Cursors了解更多创建尾光标的信息。




