MongoDB自动删除过期数据的方法(TTL索引)

  


  

  

最近由于公司业务需求,对于3个月前的过期数据需要进行删除动作,以释放空间和方便维护
  

  

本来想的是使用crontab写个脚本定时执行,但是看到Mongo本身就有自动删除过期数据的功能,所以还是用一下吧
  

  

这个方法就是使用TTL索引,后续我再写一个脚本定时删除的任务,关于TTL索引的更多使用实例,大家可以参考学习这篇文章:https://www.jb51.net/article/126810.htm
  

  

  

TTL索引是MongoDB中一种特殊的索引,可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,并且字段类型必须是日期类型或者包含有日期类型的数组(如果数组中包含多个日期类型字段,则取最早时间为过期时间)
  

  

官网介绍链接:https://docs.mongodb.com/v3.2/core/index-ttl/
  

  

  

当你在集合中某一个字段建立TTL索引后,后台会有一个单线程,通过不断查询(默认60年代一次)索引的值来判断文档是否有过期,并且删除文档的动作还依据mongod实例的负载情况,如果负载很高,可能会稍微延后一段时间再删除。
  

  

还有一个需要注意的地方,在复制集成员中,TTL后台线程只删除主要的过期数据,如果此实例变为次要角色,则后台线程闲置
  

  


  

  

和普通索引的创建方法一样,只是会多加一个属性而已
  

  

例:在log_events的集合中,createTime字段上建立一小时后过期的TTL索引
  

        祝辞db.log_events。方法createIndex ({“createTime”: 1} - - -字段名称   {expireAfterSeconds: 60 * 60}) - - -过期时间(单位秒)   祝辞db.log_events.getIndexes() - - -查看索引   (   {   “v”: 1、   “关键”:{   “_id”: 1   },   “名称”:“_id_”,   “ns”:“tt.t1”   },   {   “v”: 1、   “关键”:{   “createTime”: 1   },   “名称”:“createTime_1”,   “ns”:“tt.t1”,   “expireAfterSeconds”: 3600   }   )      


  

  

如果想更改过期时间expireAfterSeconds,可以使用collMod方法,要不然你只能只用dropIndex()方法createIndex()方法重建索引了,我想这样的方法在亿级数据量下是很头疼的
  

        db.runCommand ({collMod:“log_events”——集合名   指数:{keyPattern: {createTime: 1}, -createTime为具有TTL索引的字段名   expireAfterSeconds: 7200 - - -修改后的过期时间(秒)   }})      

虽然上面的方法可以实现自动过期删除,但是如果白天业务很忙,频繁的删除数据势必会增加负载,所以我想着晚上定时删除过期数据(如果晚上业务量少的话)
  

  


  

  

增加一个expireTime字段(用于指定过期时间),expireAfterSeconds属性值设置为0,
  

  

上面的createTime字段就不需要再有TTL索引了,这个expireTime的时间就需要在插入时指定上
  

        祝辞db.log_events。方法createIndex ({“expireTime”: 1} - - -字段名称   {expireAfterSeconds: 0}) - - -过期时间(单位秒)   祝辞db.log_events。插入({   “expireTime”:新日期(2016年1月22日23:00:00),- - - - - -此文档将在2016-1-22的23点自动删除   “logEvent”: 2   “logMessage”:“成功!”})      

这样我们就实现了,指定时间自动删除的动作了

  


  

  

有一下集中情况是无法使用TTL索引的
  

  

①TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性
  

  

②在_id主键上不能建立TTL索引
  

  

③在封顶集合中不能建立TTL索引,因为MongoDB不能从限制集合中删除文档
  

  

④你不能使用方法createIndex()去更改已经存在的TTL索引的expireAfterSeconds值,如果想更改expireAfterSeconds,可以使用collMod命令,否则你只能删除索引,然后重建了
  

  

⑤你不能在已有索引的字段上再创建TTL索引了,如果你想把非TTL索引改为TTL索引,那就只能删除重建索引了

  

  

虽然已经实现了晚上集中自动删除的功能,但是还是担心删除过大数量时负荷问题,随进行了简单测试,一查看TTL索引在亿级别集合中删除140年万过期数据的消耗
  

MongoDB自动删除过期数据的方法(TTL索引)