- TTL索引介绍和创建
TTL是一种针对日期数据类型的单字段索引的属性,通过在一个日期类型或一个包含日期类型的数组字段上创建索引并指定TTL生存周期,该字段在指定的TTL周期时间到期后会将该字段删除,适用于session,事件,log等特殊用途的数据,这些字段只需要保存一定的时间.
我们插入以下数据
db.miss_hk.insertMany([
{ "_id" : 1, "username" : "Michele Monique Reis", "metadata" : null, "lastModifiedDate" : new Date()},
{ "_id" : 2, "username" : "Chan Fat Yung", "metadata" : "world", "lastModifiedDate" : new Date() },
{ "_id" : 3, "username" : "Anita Yuen", "metadata" : { "height" : 172 }, "lastModifiedDate" : new Date() },
{ "_id" : 4, "username" : "Chingmy Yau", "metadata" : { "height" : 168, "age" : 23 }, "lastModifiedDate" : new Date() },
{ "_id" : 5, "username" : "Maggie Cheung", "metadata" : [ "actor", "model", 100 ], "lastModifiedDate" : new Date() },
{ "_id" : 6, "username" : "Cherie Chung" },
{ "_id" : 7, "username" : "Sharla Cheung" }
])
其中lastModifiedDate字段为日期类型,在该字段创建单字段索引并指定TTL,关键字expireAfterSeconds代表TTl属性,以second为单位.
> db.miss_hk.createIndex( { "lastModifiedDate" : 1 } , { "expireAfterSeconds" : 120 } )
创建完成后查看索引类型
> db.miss_hk.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.miss_hk"
},
{
"v" : 2,
"key" : {
"lastModifiedDate" : 1
},
"name" : "lastModifiedDate_1",
"ns" : "test.miss_hk",
"expireAfterSeconds" : 120 //TTL属性
}
]
那么等待120s之后,包含该索引字段的文档会自动删除,但是不包含该索引字段的文档依然存在.
> db.miss_hk.find()
{ "_id" : 6, "username" : "Cherie Chung" }
{ "_id" : 7, "username" : "Sharla Cheung" }
- TTL的具体实现过程
- 过期数据
MongoDB在每个日期类型的字段上指定过期的时间,由于每个文档的日期时间都不一致,所以MongoDB是以字段的日期值加上对应的过期时间来决定一个TTL文档何时删除,比如文档的日期时间值是"2020-06-21 12:20:35",TTL是120s,那么文档在"2020-06-21 12:22:35"就会过期.
如果是在包含日期字段的数组上创建TTL索引,那么文档的到期时间以数组中日期字段中最早的日期为准.
如果在一个非日期文档上创建TTL索引,我们可以正常创建,但是该文档不会被删除.
- 删除操作以及删除操作的时间
MongoDB的主进程mongod的一个后台线程负责读取TTL索引的值并删除从集合删除过期的文档数据.
TTL索引一旦新建完成就开始删除过期数据,而且MongoDB也不能保证TTL到期后会立刻将过期数据删除,MongoDB线程每隔60s运行一次清理过期数据的任务,所以在文档过期后如果没有到达清理线程运行的时间,数据删除操作会有一定的延迟.
在一个副本集的环境中,清理过期数据的TTL后台线程只会运行在primary节点,secondary节点只复制primary的删除命令,从而让secondary也可以删除TTL过期数据.
- TTL索引的注意事项
- TTL索引只能用在单字段,不能用于多个字段,而且单字段一定是一个日期或者包含日期的数组字段.
- _id字段不支持TTL索引.
- 固定集合不支持TTL索引
- TTL索引的过期时间只能通过删除并重建TTL索引或者通过数据库collMod命令修改.
- 如果该单字段上已经有索引,不能再创建带有TTL属性的索引.