mongo - TTL

DB/MongoDB 2014. 1. 15. 16:34


Expire Data from Collections by Setting TTL

New in version 2.2.

This document provides an introduction to MongoDB’s “time to live” or “TTL” collection feature. TTL collections make it possible to store data in MongoDB and have themongod automatically remove data after a specified number of seconds or at a specific clock time.

Data expiration is useful for some classes of information, including machine generated event data, logs, and session information that only need to persist for a limited period of time.

A special index type supports the implementation of TTL collections. TTL relies on a background thread in mongod that reads the date-typed values in the index and removes expired documents from the collection.

Considerations

  • The _id field does not support TTL indexes.
  • You cannot create a TTL index on a field that already has an index.
  • A document will not expire if the indexed field does not exist.
  • A document will not expire if the indexed field is not a date BSON type or an array of date BSON types.
  • The TTL index may not be compound (may not have multiple fields).
  • If the TTL field holds an array, and there are multiple date-typed data in the index, the document will expire when the lowest(i.e. earliest) date matches the expiration threshold.
  • You cannot create a TTL index on a capped collection, because MongoDB cannot remove documents from a capped collsection.
  • You cannot use ensureIndex() to change the value of expireAfterSeconds. Instead use the collMod database command in conjunction with the index collection flag.
  • When you build a TTL index in the background, the TTL thread can begin deleting documents while the index is building. If you build a TTL index in the foreground, MongoDB begins removing expired documents as soon as the index finishes building.

When the TTL thread is active, you will see delete operations in the output of db.currentOp() or in the data collected by thedatabase profiler.

When using TTL indexes on replica sets, the TTL background thread only deletes documents on primary members. However, the TTL background thread does run on secondaries. Secondary members replicate deletion operations from the primary.

The TTL index does not guarantee that expired data will be deleted immediately. There may be a delay between the time a document expires and the time that MongoDB removes the document from the database.

The background task that removes expired documents runs every 60 seconds. As a result, documents may remain in a collection after they expire but before the background task runs or completes.

The duration of the removal operation depends on the workload of your mongod instance. Therefore, expired data may exist for some time beyond the 60 second period between runs of the background task.

All collections with an index using the expireAfterSeconds option have usePowerOf2Sizes enabled. Users cannot modify this setting. As a result of enabling usePowerOf2Sizes, MongoDB must allocate more disk space relative to data size. This approach helps mitigate the possibility of storage fragmentation caused by frequent delete operations and leads to more predictable storage use patterns.

Procedures

To enable TTL for a collection, use the ensureIndex() method to create a TTL index, as shown in the examples below.

With the exception of the background thread, a TTL index supports queries in the same way normal indexes do. You can use TTL indexes to expire documents in one of two ways, either:

  • remove documents a certain number of seconds after creation. The index will support queries for the creation time of the documents. Alternately,
  • specify an explicit expiration time. The index will support queries for the expiration-time of the document.

Expire Documents after a Certain Number of Seconds

To expire data after a certain number of seconds, create a TTL index on a field that holds values of BSON date type or an array of BSON date-typed objects and specify a positive non-zero value in the expireAfterSeconds field. A document will expire when the number of seconds in the expireAfterSeconds field has passed since the time specified in its indexed field.[1]

For example, the following operation creates an index on the log.events collection’s createdAt field and specifies theexpireAfterSeconds value of 3600 to set the expiration time to be one hour after the time specified by createdAt.

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

When adding documents to the log.events collection, set the createdAt field to the current time:

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

MongoDB will automatically delete documents from the log.events collection when the document’s createdAt value [1] is older than the number of seconds specified in expireAfterSeconds.

[1](12) If the field contains an array of BSON date-typed objects, data expires if at least one of BSON date-typed object is older than the number of seconds specified in expireAfterSeconds.

<<<<<<< HEAD Expire at a Certain Clock Time ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ======= .. seealso:: $currentDateoperator

Expire Documents at a Certain Clock Time

>>>>>>> 9ba5a55... DOCS-2437 and DOCS-2194 edits

To expire documents at a certain clock time, begin by creating a TTL index on a field that holds values of BSON date type or an array of BSON date-typed objects and specify an expireAfterSeconds value of 0. For each document in the collection, set the indexed date field to a value corresponding to the time the document should expire. If the indexed date field contains a date in the past, MongoDB considers the document expired.

For example, the following operation creates an index on the app.events collection’s expireAt field and specifies theexpireAfterSeconds value of 0:

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

For each document, set the value of expireAt to correspond to the time the document should expire. For instance, the following insert() operation adds a document that should expire at July 22, 2013 14:00:00.

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

MongoDB will automatically delete documents from the app.events collection when the documents’ expireAt value is older than the number of seconds specified in expireAfterSeconds, i.e. 0 seconds older in this case. As such, the data expires at the specified expireAt value.



출처 - http://docs.mongodb.org/manual/tutorial/expire-data/






mongodb ttl collection 사용에 관하여(pymongo 추가)

IT아저씨 Barracuda | 2012/11/10 15:09 | DBMS

 

[mongodb client UI]


MongoDB 2.2.x 2.1.2 부터 TTL(Time To Live) 기능이 제공되고 있다. IT에 익숙한 분이라면 icmp, DNS, cache server 등의 프로토콜이나 설정/작동 방법상에서 자주 나타나는 용어라는 것을 알 수 있으리라.


mongodb에서의 이 기능은 단순하게 설명하자면, 지정된 시간 이전의 레코드를 자동으로 지우는(purging, removing) 기능이다. 주로 통계성 데이터나 모니터링 데이터 등 시계열 데이터가 저장되어 있을 경우나 일정 시간 동안만 저장되어야 하는 session 정보 등을 저장하는데 유용하게 사용할 수 있겠다.

중요한 주의사항 몇 가지를 아래에 정리해 두고 테스트를 진행해 본다.
  1. mongodb의 Date 에 해당하는 날짜시간 데이터가 저장되는 필드가 필요하고, 여기에 ensureIndex로 인덱스를 두는 방식이다
  2. 해당 필드는 다른 index 에 복합적으로 참조되지 않아야 한다(단일 필드, 단일 인덱스)
  3. 해당 필드에는 위 1번에서 처럼 Date BSON type의 데이터가 UTC 기준으로 저장되어야 자동으로 지워진다
  4. mongodb의 ttl thread는 1분단위로 동작한다. 즉 10초로 설정한다고 데이터 저장 후 10초만에 지워지는 것이 아니라 1분 가량의 오차가 존재하며, DB 시스템의 부하 정도(mongod의 workload가 얼마나 큰지)에 따라 달라질 수 있다는 즉, 정확히 해당 시간 경과후 지워진다는 보장은 없다는 것.
  5. 모든 컬렉션의 공통 필드인 _id 필드는 ttl 필드로 사용할 수 없다.
  6. capped collection은 ttl index를 적용할 수 없다.

각설하고, 아래와 같이 간단히 테스트 해 본다

> db.tt_col.save( { id: 'id1', name: 'aaa', dt: new Date() } );
> db.tt_col.save( { id: 'id2', name: 'bbb', dt: new Date() } );
> db.tt_col.save( { id: 'id3', name: 'ccc', dt: new Date() } );
> db.tt_col.find();
{ "_id" : ObjectId("509de58b1493b98702441310"), "id" : "id1", "name" : "aaa", "dt" : ISODate("2012-11-10T05:26:35.370Z") }
{ "_id" : ObjectId("509de5ac1493b98702441311"), "id" : "id2", "name" : "bbb", "dt" : ISODate("2012-11-10T05:27:08.218Z") }
{ "_id" : ObjectId("509de5ba1493b98702441312"), "id" : "id3", "name" : "ccc", "dt" : ISODate("2012-11-10T05:27:22.450Z") }
> db.tt_col.ensureIndex( {dt: 1}, {expireAfterSeconds: 10} );
> db.tt_col.find();
{ "_id" : ObjectId("509de58b1493b98702441310"), "id" : "id1", "name" : "aaa", "dt" : ISODate("2012-11-10T05:26:35.370Z") }
{ "_id" : ObjectId("509de5ac1493b98702441311"), "id" : "id2", "name" : "bbb", "dt" : ISODate("2012-11-10T05:27:08.218Z") }
{ "_id" : ObjectId("509de5ba1493b98702441312"), "id" : "id3", "name" : "ccc", "dt" : ISODate("2012-11-10T05:27:22.450Z") }
잘 보면 날짜/시간 부분이 localtime이 아닌 UTC 기준시간으로 저장되어 있음에 유의한다.

약 40초 후에 컬렉션의 데이터를 조회해 보니 3건의 데이터가 삭제되어 있음을 확인할 수 있다. 
> db.tt_col.find().count();
0
> db.tt_col.find();
>


응용할 수 있는 트릭이라면, 지워지게 하고 싶지 않은 데이터가 있을 경우 어떨게 하면 될까?


한 가지 방법은 보관이 필요한 데이터를 찾아서 ttl 설정 필드 값을 Date() 로 update하는 것이다. 만약 계속 보존처리를 해야 한다면 매번 update를 수행해야 할 것이고,

계속 보존해야 한다면, 단순하게도 다음과 같이 ttl 필드를 Date가 아닌 다른 데이터 값으로 설정하면 된다.

> db.tt_col.update( { id: 'id1' }, { dt: null } );


[pymongo 2.3]

사용 방법은 유사하지만 python 내에서 ttl 기능 설정/사용시에 유의할 사항이 있다. 아래 예시의 함정을 찾아 보자.


Python 2.7.2 (default, Aug 19 2011, 20:41:43) [GCC] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import pymongo

>>> from datetime import datetime, date, time, timedelta

>>> datetime.now()

datetime.datetime(2012, 11, 2, 2, 3, 50, 18750)

>>> pyMongoConnStr = 'mongodb://10.10.10.70:28017/myschema'

>>> connMongo = pymongo.Connection( pyMongoConnStr )

>>> connMongo.myschema.tt_col.save( { 'a':1, 'b':2, 'dt': datetime.now() } )
ObjectId('50aa68a94422527639f91a34')
>>> connMongo.monitor.t_col.ensure_index( 'dt', pymongo.ASCENDING, expireAfterSeconds = 15 )
>>> connMongo.myschema.tt_col.find_one()
{u'a': 1, u'dt': datetime.datetime(2012, 11, 2, 2, 13, 13, 517000), u'_id': ObjectId('50aa68a94422527639f91a34'), u'b': 2}


15초 가량 후에 해당 row가 삭제되어야 하는데, 10분이 지나도 멀쩡하게 남아 있다. index 설정을 봐도 잘못 된게 없고, 시스템 시간도 정확하게 현재시간을 가리키고 있는데, ...


결론을 말하자면, 위에서 등록한 row는 한국 시간으로 9시간 가량 후에 지워질 것이다. 왜냐하면 mongodb의 ttl thread 는 UTC 를 기준으로 작동하는데, python에서 mongodb에 등록한 데이터(row)에서 dt 필드의 값인 datetime.now() 는 KST(대한민국표준시; 또는 시스템 시간이 localtime) 기준의 시간 값이기 때문이다. 즉 python에서 ttl index 필드의 시간 값을 설정할 때는 반드시 datetime.utcnow() 를 사용하여야만 한다. 이점 유의하자.



출처 - http://bryans.tistory.com/m/post/view/id/79















'DB > MongoDB' 카테고리의 다른 글

mongodb - User Privilege Roles  (0) 2014.02.23
mongodb - backup  (0) 2014.02.23
mongodb - 콜렉션 필드 형변환 (How to change the type of a field)  (0) 2013.10.07
mongodb - Query, Update and Projection Operators  (0) 2013.07.23
mongodb - GridFS  (0) 2013.06.18
Posted by linuxism
,