zoukankan      html  css  js  c++  java
  • mongo ttl索引

    db.log_events.find()                                     # 查找log_events里的所有数据
     
    db.log_events.createIndex( { "LogDT": 1 }, { expireAfterSeconds: 3600 } )                              #设置log_events里的TTL过期索引清理时间为3600秒
     
    db.runCommand( { collMod: "log_events",index: { keyPattern: { LogDT: 1 },expireAfterSeconds: 10800 }})       #修改过期索引时间,建议最好还是先drop在新建
     
    db.log_events.getIndexes()                 #查找log_events里的所有索引
     
     
     
    TTL索引是MongoDB中一种特殊的索引, 可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,
    并且字段类型必须是date类型或者包含有date类型的数组(如果数组中包含多个date类型字段,则取最早时间为过期时间)
     
    当你在集合中某一个字段建立TTL索引后,后台会有一个单线程,通过不断查询(默认60s一次)索引的值来判断document是否有过期,
    并且删除文档的动作还依据mongod实例的负载情况,如果负载很高,可能会稍微延后一段时间再删除。
    还有一个需要注意的地方,在复制集成员中,TTL后台线程只删除primary的过期数据,如果此实例变为secondary角色,则后台线程闲置
     
    限制条件:
    有一下集中情况是无法使用TTL索引的
    ①TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性
    ②在_id 主键上不能建立TTL索引
    ③在capped collection中不能建立TTL索引,因为MongoDB不能从capped collection中删除文档
    ④你不能使用createIndex()去更改已经存在的TTL索引的expireAfterSeconds值,如果想更改expireAfterSeconds,可以使用collMod命令,
    否则你只能删除索引,然后重建了
    ⑤你不能在已有索引的字段上再创建TTL索引了,如果你想把非TTL索引改为TTL索引,那就只能删除重建索引了
     
    验证:
    虽然已经实现了晚上集中自动删除的功能,但是还是担心删除过大数量时负荷问题,随进行了简单测试,一查看TTL索引在亿级别集合中删除140万过期数据的消耗
    测试配置:
         OS:Vm虚拟机
         CPU: 4
         内存:8
    集合数据量:
    > db.t1.count()
    104273617
    因为我制造测试数据时,_id是顺序增加的,所以我直接查看_id=1500000的那笔数据的createTime,然后自己计算一下此createTime和当前时间的时间差,
    随后根据这个时间差来更改expireAfterSeconds的值,以让这150万数据5分钟后过期并删除。
    在修改完expireAfterSeconds后,就严密延时“ vmstat 1 ” 命令的输出数据;
    我的测试结果:
    删除操作整个过程在90秒左右完成;
    CPU最高占用90%,平均在50%
    内存占用3G
    这个也是特别准确的模拟情况,只是粗略的了解一下TTL索引的资源消耗,以决定是不是需要这样的方式来实现删除过期数据
              监控vmstat的截图:

     

    创建TTL索引方法:
    和普通索引的创建方法一样,只是会多加一个属性而已
    例:在log_events的集合中,createTime 字段上建立一小时后过期的TTL索引
       
    [sql] view plain copy
     
    1.  >db.log_events.createIndex( { "createTime": 1 },     ---字段名称   
    2.                                 { expireAfterSeconds: 60*60 } )     ---过期时间(单位秒)  
    3. >db.log_events.getIndexes()     ---查看索引  
    4. [  
    5.         {  
    6.                 "v" : 1,  
    7.                 "key" : {  
    8.                         "_id" : 1  
    9.                 },  
    10.                 "name" : "_id_",  
    11.                 "ns" : "tt.t1"  
    12.         },  
    13.         {  
    14.                 "v" : 1,  
    15.                 "key" : {  
    16.                         "createTime" : 1  
    17.                 },  
    18.                 "name" : "createTime_1",  
    19.                 "ns" : "tt.t1",  
    20.                 "expireAfterSeconds" : 3600  
    21.         }  
    22. ]  
    修改TTL索引的expireAfterSeconds属性值:
    注:如果想更改过期时间expireAfterSeconds,可以使用collMod方法,要不然你只能只用dropIndex(),createIndex()方法重建索引了,我想这样的方法在亿级数据量下是很头疼的
    [sql] view plain copy
     
    1. db.runCommand( { collMod: "log_events",     ---集合名  
    2.                 index: { keyPattern: { createTime: 1 },     ---createTime为具有TTL索引的字段名  
    3.                           expireAfterSeconds: 7200          ---修改后的过期时间(秒)  
    4.                         }})  
    虽然上面的方法可以实现自动过期删除,但是如果白天业务很忙,频繁的删除数据势必会增加负载,所以我想着晚上定时删除过期数据(如果晚上业务量少的话)
    方法如下:
    增加一个expireTime字段(用于指定过期时间),expireAfterSeconds属性值设置为0,
    注:上面的createTime字段就不需要再有TTL索引了,这个expireTime的时间就需要在插入时指定上
    [sql] view plain copy
     
    1. >db.log_events.createIndex( { "expireTime": 1 },     ---字段名称  
    2.                                 { expireAfterSeconds: 0 } )     ---过期时间(单位秒)  
    3. >db.log_events.insert( {  
    4.   "expireTime": new Date('Jan 22, 2016 23:00:00'),     ---此文档将在2016-1-22的23点自动删除  
    5.   "logEvent": 2,  
    6.   "logMessage": "Success!"} )  


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

    一、TTL索引

    创建方法
            db.collection.createIndex(keys, options)
            options:
                    expireAfterSeconds 指定多少秒或者包含日期值的数组
    
    创建示例
            db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )  
    
    何时失效
            在指定的时间达到后失效,也即是索引字段的值加上一个特定的秒数之后
            如果索引字段是一个数组,即索引字段上存在着多个日期值,此时MongoDB取最小值加上失效时间(lowest())
            对于非日期字段或不包含日期数组的索引字段,文档不会失效
            对于不包含索引字段的文档,文档不会失效
    
    删除操作
            mongod的一个后台线程会读取索引的值并将失效的文档从集合移除
            当TTL线程被激活后,可以从db.currentOp()或者从profile观察到删除操作
    
    何时删除
            当基于后台方式创建索引时,TTL线程能够在索引创建期间开始删除失效文档
            当基于前台方式创建索引时,TTL线程在索引创建完成后开始删除失效文档      
            TTL索引的删除不能完全保证失效期后一定删除,存在一定延迟(取决于mongod的工作负载)
            TTL删除文档后台线程每60s移除失效文档(因此可能存在已过失效期,文档还在的情形)
            在副本集环境中,TTL后台线程仅仅在主副本上工作,辅助副本上由复制操作实现
            在使用TTL索引查询时,与使用非TTL索引一样
    
    一些限制
            不能基于已经存在索引的字段创建TTL索引以及非日期字段创建TTL索引,文档不会失效
            TTL索引不支持基于多个字段的复合索引
            不支持定长集合

    二、TTL索引示例

    # mongo --shell localhost:27000 TTLData.js  
    MongoDB shell version: 3.2.11
    connecting to: localhost:27000/test
    
    repSetTest:PRIMARY> addTTLTestData()  //添加集合数据
    Create three records in database each with a create time that is 1 minute apart
    Created three test documents, oldest being 4 mins old
    Now create a TTL index with expiry of 5 mins on the createDate field as follows
    db.ttlTest.ensureIndex({createDate:1}, {expireAfterSeconds:300})
    
    repSetTest:PRIMARY> db.ttlTest.find()   //当前向集合里插入了3个文档
    { "_id" : 1, "createDate" : ISODate("2017-03-10T03:23:01.169Z") }
    { "_id" : 2, "createDate" : ISODate("2017-03-10T03:24:01.169Z") }
    { "_id" : 3, "createDate" : ISODate("2017-03-10T03:25:01.169Z") }
    
    //下面为测试集合上的文档添加索引,即5分钟后索引失效
    repSetTest:PRIMARY> db.ttlTest.createIndex({createDate:1}, {expireAfterSeconds:300})
    {
            "createdCollectionAutomatically" : false,
            "numIndexesBefore" : 1,  // Author : Leshami
            "numIndexesAfter" : 2,   // Blog   : http://blog.csdn.net/leshami
            "ok" : 1
    }
    
    //查找文档
    repSetTest:PRIMARY> db.ttlTest.find()
    { "_id" : 1, "createDate" : ISODate("2017-03-10T03:23:01.169Z") }
    { "_id" : 2, "createDate" : ISODate("2017-03-10T03:24:01.169Z") }
    { "_id" : 3, "createDate" : ISODate("2017-03-10T03:25:01.169Z") }
    
    //当指定时间到期后,文档被删除,如下,查询不到任何文档
    repSetTest:PRIMARY> db.ttlTest.find()
     
  • 相关阅读:
    [转]创建节约内存的JavaBean
    TCP协议
    redis常用命令
    Windows&Linux常用命令笔记
    二叉树学习笔记
    云计算入门
    redis主从切换
    spring 异步处理request
    ibatis工作原理
    工作了3年的JAVA程序员应该具备什么技能?(转)
  • 原文地址:https://www.cnblogs.com/liqing1009/p/8421621.html
Copyright © 2011-2022 走看看