TTL Indexes
注意
如果您为了节省存储成本而删除文档,可以考虑 MongoDB Atlas 中的 Online Archive。Online Archive 可自动将不常访问的数据存档到完全托管的 S3 存储桶,以实现经济高效的数据分层。
TTL 索引是特殊的单字段索引,MongoDB 可以在一定时间后或在特定时钟时间使用这种索引自动从集合中删除文档。数据过期对于某些类型的信息(例如机器生成的事件数据、日志和会话信息)很有用,这些信息仅需要在数据库中保留有限的时间。
您可以 在 UI 中为 MongoDB Atlas 托管的部署创建和管理 TTL 索引。
创建 TTL 索引
警告
创建 TTL 索引后,可能需要一次性删除大量符合条件的文档。如此大的工作负载可能会导致服务器出现性能问题。为了避免此类问题,请计划在非工作时间创建索引,或者在为将来的文档创建索引之前,批量删除符合条件的文档。
要创建 TTL 索引,请使用 createIndex()
。指定一个日期类型或包含日期类型值的数组的索引字段。使用 expireAfterSeconds
选项指定 TTL 值(以秒为单位)。
TTL 索引 expireAfterSeconds
值必须介于 0
和 2147483647
(包含两者)之间。
示例,要在eventlog
集合的lastModifiedDate
字段上创建TTL值为3600
秒的TTL索引,请在mongosh
中使用以下操作:
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
行为
数据过期
TTL 索引在索引字段值后经过指定的秒数后使文档过期。过期阈值为已编入索引的字段值加上指定的秒数。
如果字段为数组,且索引中有多个日期值,MongoDB 会使用数组中最低(最早)日期值计算过期阈值。
如果文档中的索引字段不是日期或保存一个或多个日期值的数组,则文档不会过期。
如果文档不包含索引字段,则文档将不会过期。
删除操作
mongod
中的后台线程会读取索引中的值,并从集合中删除过期文档。
TTL 线程执行的正在进行的删除操作出现在 db.currentOp()
输出中。随着 TTL 线程删除文档,metrics.ttl.deletedDocuments
服务器状态指标会增加。
如果时间序列集合包含时间戳在 1970-01-01T00:00:00.000Z
之前或 2038-01-19T03:14:07.000Z
之后为 timeField
的文档,则 TTL“生存时间”功能不会从集合中删除任何文档。
删除操作的时间
索引在主节点上构建完成后,MongoDB 会立即删除过期文档。 有关索引构建过程的更多信息,请参阅在已填充collection上构建索引。
TTL 索引并不保证过期数据会在过期后立即删除。 文档过期时间和 MongoDB 从数据库中删除文档的时间之间可能存在延迟。
删除过期文档的后台任务每 60 秒运行一次。因此,在文档过期和后台任务运行之间的时间段内,文档可能会保留在集合中。MongoDB 在索引完成后 0 到 60 秒开始删除文档。
由于删除操作的持续时间取决于 mongod
实例的工作负载,因此过期数据可能会在后台任务运行之间的 60 秒间隔时间以后存在一段时间。
由 TTL 任务启动的删除操作在前台运行,就像其他删除操作一样。
副本集
在副本集成员上,TTL 后台线程只在成员处于主状态时删除文档。当成员处于从状态时,TTL 后台线程处于空闲状态。从成员复制主成员的删除操作。
支持查询
TTL 索引支持查询的方式与非 TTL 索引相同。
限制
TTL索引是单字段索引。 复合索引不支持TTL ,并忽略
expireAfterSeconds
选项。_id
字段不支持 TTL 索引。无法在固定大小集合上创建 TTL 索引。
您无法在时间序列集合上创建 TTL 索引。 通过自动删除time-series collection来提供类似的功能。
不能使用
createIndex()
更改现有索引的expireAfterSeconds
值。 而是将collMod
数据库命令与index
集合标志结合使用。 否则,要更改现有索引的选项值,必须先删除索引并重新创建。如果某个字段已存在非 TTL 单字段索引,则无法对同一字段创建 TTL 索引,因为无法创建具有相同键规范且仅选项不同的索引。 要将非 TTL 单字段索引更改为 TTL 索引,必须先删除该索引,然后使用
expireAfterSeconds
选项重新创建。