有上限集合(Capped collections):
Capped集合是固定大小的集合,支持基于插入顺序插入和检索文档的高吞吐量操作。Capped集合的工作方式类似于循环缓冲区:一旦集合填满了它分配的空间,它就会通过覆盖集合中最早的文档来为新文档腾出空间
作为有上限的集合的另一种选择,考虑MongoDB的TTL(生存时间)索引。如通过设置TTL使集合中的数据过期,这些索引允许您根据日期类型字段的值和索引的TTL值从普通集合中过期并删除数据。
TTL索引与有上限的集合不兼容。
特点
插入顺序
有上限的集合保留插入顺序。查询不需要索引,按插入顺序返回文档。没有这种索引开销,capped集合可以支持更高的插入吞吐量。
自动删除最旧的文档
为新文档腾出空间,有上限的集合自动删除集合中最早的文档,不需要脚本或显式删除操作。
_id索引
默认情况下,Capped集合有一个_id字段和一个_id字段上的索引。
使用场景:
存储大容量系统产生的日志信息。在没有索引的有上限集合中插入文档的速度接近于直接将日志信息写入文件系统的速度。此外,内置的先进先出属性在管理存储使用时,维护事件的顺序。
在有上限的集合中缓存少量数据。因为缓存的读量比写量大,所以您需要确保这个集合始终保持在工作集中(即在RAM中),或者对所需的索引或索引接受一些写惩罚。(一种缓存)
限制和建议
读
从MongoDB 5.0开始,当从一个capped集合中读取时,你不能使用read concern “snapshot”。
更新
如果计划更新有上限的集合中的文档,请创建索引,以便这些更新操作不需要进行集合扫描。
文档大小
如果更新或替换操作更改了文档大小,则操作将失败。
删除文档
不能从有上限的集合中删除文档。要从集合中删除所有文档,请使用drop()方法删除集合并重新创建有上限的集合。
分片
不能对有上限的集合进行分片
查询效率
使用自然排序从集合中有效地检索最近插入的元素。这类似于在日志文件上使用tail命令。
聚合$out
聚合管道阶段$out不能将结果写入有上限的集合。
事务
从MongoDB 4.2开始,你不能在事务中写入有上限的集合
创建有上限集合
使用db.createCollection()方法显式创建有上限的集合。当创建一个有上限的集合时,您必须以字节为单位指定该集合的最大大小,MongoDB将为该集合预先分配。capped集合的大小包括用于内部开销的少量空间。
# 创建有上限集合log,大小100k
# 如果size字段小于或等于4096,那么集合的上限为4096字节。否则,MongoDB会将提供的大小提高到256的整数倍。
db.createCollection( "log", { capped: true, size: 100000 } );
# 输出
{ "ok" : 1 }
# max设置集合最大文档数
# 如果一个集合在达到最大文档数之前达到了最大大小限制,MongoDB将删除旧文档。
db.createCollection("log", { capped : true, size : 5242880, max : 5000 } );
# 如果在有上限的集合执行find(), MongoDB会保证结果的顺序与插入顺序相同。
# 要以反向插入顺序检索文档,使用find()和sort()方法,并将$natural参数设置为-1
db.log.find().sort( { $natural: -1 } );
# 检查集合是否是有上限的
db.log.isCapped();
# 可以使用convertToCapped命令将非上限集合转换为上限集合
# 在操作期间持有数据库排他锁。同一数据库的其他操作将被阻塞,直到该操作完成
db.runCommand({"convertToCapped": "mycoll", size: 100000});