MongoDB定容集合(Capped Collection)

目录

定容集合

定容集合行为

使用场景

限制和建议

使用方法

构建定容集合

查询

确定集合是否定容

将集合转换成定容集合

修改空间大小

修改文档数量限制

末尾持续游标(tailable cursor)


Mongodb的文档保存在集合当中,类似关系型数据库当中的表。用户对集合进行增删改查操作。

定容集合

定容集合,是一种固定大小的集合。支持数据的快速插入和按照插入顺序的高速读取。定容集合工作机制类似循环缓存。当集合大小达到用户指定的大小时,新插入的数据会覆盖最早插入的数据。

作为定容集合的替代方案,用户还可以选择定时索引。建立索引是指定索引数据的过期时间。当插入数据的时间索引字段超过过期时间后,mongodb或自动清除该数据。本文终点探讨定容集合,定时索引内容请参照其他文档。

定容集合行为

定容集合容量大小是确定的,并且保证数据按照插入顺序排列,因此具有下面的几个行为。

  • 数据按照插入时间排序,查询时无需构建其他时间字段索引来对文档查询顺序。因此提高了数据插入性能。
  • 自动删除最先插入的数据。当达到容量限制时,定容集合自动删除最先插入的数据,无需显示执行删除操作或额外的删除脚本。
  • 定容集合有_id字段和_id字段索引。

使用场景

针对定容集合高效插入和保证按照插入顺序读取数据的特性,定容集合适应下面两个场景

  1. 保存系统日志。 因为无需构建额外的索引,索引向定容集合插入数据时,具备与直接写入文件系统类似的性能。其先入先出的特性,保证了写入时间的顺序。因此适合用来保存系统日志。 mongodb的oplog就使用了定容集合。
  2. 将定容集合作为缓存,保存少量数据。

限制和建议

  • 自mongodb5开始,定容集合禁止使用snapshot读取方式
  • 当用户更新定容集合的数据时,可以添加索引避免全表扫描。当然,更新完成后,建议删除改索引。
  • 定容集合,不可分片
  • 使用默认排序可以高效的读取定容集合数据,这与在unix系统中使用tail方法读取日志文件类似。
  • 禁止使用$out方法向定容集合写入数据
  • 禁止在mongodb事务中向定容集合写入数据。

使用方法

构建定容集合

使用db.createCollection()方法,显式创建定容集合。定义定容集合时,必须指定集合空间大小。mongodb在分配定容集合存储空间时,按照256bytes的倍数来分配大小。mongodb计算出小于用户指定空间大小的最大的256的倍数。定容集合最大存储空间,不能超过1PB。

db.createCollection("<collectionName>", {capped: true, size: <collection_size>}) 

其中,collection_size的单位是字节(bytes)

db.createCollection("log", {capped: true, size: 100000})

db.getCollectionInfos({name: "log"})
{
	"name" : "log",
	"type" : "collection",
	"options" : {
		"capped" : true,
		"size" : 100000
	},
	"info" : {
		"readOnly" : false,
		"uuid" : UUID("d11d3f1b-74ff-4dcc-89e3-e43051c8e3d7")
	},
	"idIndex" : {
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	}
}

除了指定集合空间大小之外,用户还可以指定集合文档的数量

db.createCollection("log", {capped: true, size:100000, max:500})

db.getCollectionInfos({name: "log"})
{
	"name" : "log",
	"type" : "collection",
	"options" : {
		"capped" : true,
		"size" : 100000,
		"max" : 500
	},
	"info" : {
		"readOnly" : false,
		"uuid" : UUID("38120a0b-31e9-471e-a15d-45dbf3314323")
	},
	"idIndex" : {
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	}
}

定容集合中,必须指定大小。当定容集合容量已满而未达到用户指定的最大文档数量时,定容集合会删除最先插入的数据。

查询

使用find()方法查询定容集合。如果没有指定排列顺序,数据按照插入顺序返回。

db.cappedCollection.find()

如果查询插入数据的倒序,需要在查询语句中指定排列顺序。

db.cappedCollection.find().sort({$natural: -1})

确定集合是否定容

使用命令isCapped()查看一个集合是否是定容集合。

db.collection.isCapped()

db.log.isCapped()
true

将集合转换成定容集合

使用命令convertToCapped, 将非定容集合转换成定容集合。但必须指定定容集合所占空间大小。集合转换为定容集合时,mongodb会为当前集合添加排它锁。其他人任何操作本集合的操作,需要等待定容集合转换完成

db.runCommand( {"convertToCapped": "<collection_name>", size: 100000})

db.runCommand( {"convertToCapped": "books", size: 100000})

db.books.isCapped()
true

修改空间大小

在collMod中,使用cappedSize指定定容集合空间大小。最大空间可超过1PB。

db.runCommand( {collMod: "log", cappedSize: 100000})

修改文档数量限制

在collMod中,使用cappedMax指定已有定容集合文档数量。当cappedMax值定义为负数或0时,没有文档数量限制。当指定的cappedMax数量小于当前定容集合文档数量时,定容集合会按照文档插入顺序,删除超过数量限制的文档。

db.runCommand( {collMod: "log", cappedMax: 500})

末尾持续游标(tailable cursor)

定容集合支持一种特殊的游标。当游标读取到最后一个文档后,该游标不会关闭,等到有新的数据插入到定容集合时,该游标返回新插入的数据,并保持开启状态。这与unix中的命令tail -f类似,直到文件结束,命令才终止。

tailableCursor比使用索引,按照插入的自然顺序返回数据。这样从头读取集合中的数据,对数据库和网络的开销是巨大的。但游标耗尽走到最后读取新插入的数据时,开销是微小的。