MongoDB TTL 인덱스
MongoDB TTL 인덱스 (TTL Indexes)
일정 시간이 지나면 자동으로 도큐먼트를 지우고 싶을 때 TTL(Time-to-live) 인덱스를 써요. TTL 인덱스는 MongoDB가 정해진 시간이 지나거나 특정 시각이 되면 컬렉션에서 도큐먼트를 자동으로 제거해 주는 특수한 단일 필드 인덱스예요. 세션, 로그, 임시 데이터처럼 수명이 정해진 데이터를 정리할 때 유용합니다.
TTL 인덱스 만들기
createIndex()를 호출하면서 날짜 타입(또는 날짜 값들을 담은 배열)인 필드를 지정하고, expireAfterSeconds 옵션으로 초 단위 수명을 넣으면 돼요. 예를 들어 eventlog 컬렉션의 lastModifiedDate 필드에 3600초 수명의 TTL 인덱스를 만들고 싶다면 이렇게 해요.
db.eventlog.createIndex(
{ "lastModifiedDate": 1 },
{ expireAfterSeconds: 3600 }
)
기존 인덱스를 TTL로 바꾸기
이미 있는 비-TTL 단일 필드 인덱스를 TTL 인덱스로 바꾸려면 collMod 데이터베이스 명령을 써요.
db.runCommand({
"collMod": <collName>,
"index": {
"keyPattern": <keyPattern>,
"expireAfterSeconds": <number>
}
})
예를 들어 { "lastModifiedDate": 1 } 패턴의 비-TTL 인덱스를 수명 100초의 TTL 인덱스로 바꾸려면 이렇게 해요.
db.runCommand({
"collMod": "tickets",
"index": {
"keyPattern": { "lastModifiedDate": 1 },
"expireAfterSeconds": 100
}
})
만료와 삭제 동작
- 인덱스 필드에 날짜 값이 없는 도큐먼트나 인덱스 필드 자체가 없는 도큐먼트는 만료되지 않아요.
mongod의 백그라운드 스레드가 인덱스의 값을 읽어 만료된 도큐먼트를 컬렉션에서 제거해요.- TTL 스레드가 진행 중인 삭제 작업은
db.currentOp()출력에 나타나고, 삭제할 때마다metrics.ttl.deletedDocuments서버 상태 메트릭이 올라가요. - MongoDB 6.1부터는 효율을 위해 여러 도큐먼트 삭제를 함께 배치할 수 있고,
explain결과에BATCHED_DELETE스테이지가 포함돼요.
삭제 과정과 시점
TTL 백그라운드 삭제는 각 TTL 인덱스를 돌며 만료된 도큐먼트를 지워요. 한 인덱스에서 다음 조건 중 하나가 충족되면 다음 인덱스로 넘어가요.
- 현재 인덱스에서 도큐먼트 50000개를 삭제한 경우
- 현재 인덱스 삭제에 1초를 소비한 경우
- 현재 인덱스의 만료 도큐먼트를 모두 삭제한 경우
TTL 삭제는 단일 스레드 백그라운드 작업이라 동시에 돌지 않아요. 부하가 크거나 만료 도큐먼트가 많으면 삭제가 오래 걸릴 수 있어요. 또 삭제 루프는 60초마다 멈추며 큰 삭제 하나에 너무 오래 쓰는 걸 막아요. TTL 배경 작업은 60초마다 실행되므로, 만료된 뒤 삭제되기까지 최대 0~60초의 지연이 있을 수 있어요. 인덱스 수명값(expireAfterSeconds)을 줄여도 전체 인덱스 재구축은 일어나지 않지만, 한꺼번에 만료되는 도큐먼트가 많아지면 삭제 연산이 늘어나 성능 문제가 생길 수 있어요.
복제 세트에서는
복제 세트 구성원에서는 멤버가 primary 상태일 때만 TTL 백그라운드 스레드가 삭제해요. secondary 상태에서는 스레드가 대기하고, 보조 멤버는 프라이머리에서 발생한 삭제 연산을 복제해요.