OPTIONS
翻译或纠错本页面

通过设置TTL使集合中的数据过期

2.2 新版功能.

本文对MongoDB的 “存活时间” 或者叫作”TTL“的集合特性进行了介绍。TTL集合能让存储在MongoDB中的数据在指定的秒数后或在指定的时钟时间被 mongod 自动删除。

数据过期对某些类型的信息很有用,包括机器生成的事件数据、日志以及只需要存在一段有限时间内的会话信息。

一个特别的索引类型支撑了TTL集合的实现。TTL依赖一个在 mongod 中的后台线程,该线程读取索引中日期类型的值并从集合中删除过期的 documents

须知

  • The _id field does not support TTL indexes.
  • 你不能在一个已经有索引的字段上创建TTL索引。

  • 如果文档不存在被索引的字段,该文档不会过期。

  • 如果被索引的字段不是日期 BSON type 或是日期数组 BSON types,文档不会过期。

  • TTL索引不能是复合索引(不能有多个字段)。

  • 如果TTL字段容纳了一个数组并且在索引中有多个日期类型的数据,文档将在 最小的 (即最早的)日期等于过期临界值时过期。

  • 你不能在一个固定集合上创建TTL索引,因为MongoDB不能从固定集合中删除文档。

  • 你不能使用 ensureIndex() 改变 expireAfterSeconds 的值。作为替代,请使用 collMod 数据库命令连同 index 集合标志。

  • 当你在 background 创建一个TTL索引时,TTL线程可以在创建索引的同时开始删除文档。如果你在前台创建一个TTL索引,一旦索引完成创建,MongoDB就开始删除过期的文档。

当TTL线程活跃着时,你可以在 db.currentOp() 的输出和 database profiler 收集的数据中看到 delete 操作。

当在 replica sets 上使用TTL索引时,TTL后台线程 删除在 primary 成员中的文档。不过,TTL后台线程 确实 也运行在从节点上。 Secondary 成员从主节点复制删除操作。

TTL索引不保证过期的数据会立即被删除。从文档过期到文档被MongoDB从数据库中删除有一个延迟。

删除过期文档的后台任务 每60秒 运行一次。因此,文档在他们 过期后*但在后台任务 *运行并完成前 仍会留在集合中。

删除操作持续的时间由你的 mongod 实例的工作负荷决定。因此,某些时候,过期的数据可能会在两次后台任务运行之间存在 超过 60秒的时间。

所有拥有设置了 expireAfterSeconds 选项的索引的集合都启用了 usePowerOf2Sizes。用户不能修改该设置。作为启用 usePowerOf2Sizes 的结果,MongoDB必须分配比数据大小更多的磁盘空间。这种方法有助于降低频繁的删除造成存储碎片的可能性并产生更多的可预测的存储使用模式。

步骤

对一个集合启用TTL,如下例子所示,使用 ensureIndex() 方法创建一个TTL索引。

除了后台线程之外,TTL索引也以和普通索引做的同样地方式支持查询。你可以用两种方式中的一种使用TTL索引使文档过期,要么:

  • 在(文档)创建之后一定的秒数删除文档。这样的TTL索引还会支持对于文档创建时间的查询。或者,

  • 指定一个显示过期时间。这种TTL索引将支持对文档过期时间的查询。

使文档在一定的秒数后过期

为了使文档在一定的秒数后过期,在容纳BSON日期类型或BSON日期类型对象数组的值的字段上创建TTL索引 expireAfterSeconds 指定一个正的非零值。当被索引字段 [1] 指定的时间经过了 expireAfterSeconds 字段中的秒数时,文档将会过期。

例如,如下操作在 log_events 集合的 createdAt 字段创建了一个索引并指定 expireAfterSeconds 的值为 3600 以使过期时间为 createdAt 指定的时间之后的一小时。

db.log_events.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

当向 log_events 集合添加文档时,设置 createdAt 字段为当前时间:

db.log_events.insert( {
   "createdAt": new Date(),
   "logEvent": 2,
   "logMessage": "Success!"
} )

当某文档的 createdAt 字段的值 [1] 晚于 expireAfterSeconds``中指定的秒数时,MongoDB会自动从 ``log_events 集合删除该文档。

[1](1, 2)

如果该字段包含一组BSON日期类型的对象,如果至少有一个BSON日期类型的对象晚于 ``expireAfterSeconds``中指定的秒数,数据过期。

参见

$currentDate 操作符

使文档在确定的时钟时间过期

为了使文档在一个确定的时钟时间过期,首先在一个容纳BSON日期类型或BSON日期类型对象数组的值的字段上创建TTL索引 expireAfterSeconds 指定为 0。对于集合中的每个文档,设置其被索引的日期字段为与文档过期的时间一致的值。如果被索引字段包含了一个过去了的日期,MongoDB认为该文档过期。

例如,如下操作在 log_events 集合的 createdAt 字段创建了一个索引并指定 expireAfterSeconds 的值 0

db.log_events.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

对于每个文档,设置 expireAt 的值与文档过期的时间一致。举例来说,如下的 insert() 操作添加了一个将在 2013年7月22号 14:00:00 过期的文档。

db.log_events.insert( {
   "expireAt": new Date('July 22, 2013 14:00:00'),
   "logEvent": 2,
   "logMessage": "Success!"
} )

当某文档的 expireAt 字段的值晚于 expireAfterSeconds``中指定的秒数时——在本例中也就是  ``0 ,MongoDB会自动从 log_events 集合删除该文档。因此,数据在指定的 expireAt 值过期。