MongoDB 디스크 공간 관리 및 축소를 위한 모범 사례
이 포괄적인 모범 사례 가이드를 통해 MongoDB 디스크 사용량을 최적화하세요. 컬렉션과 인덱스 압축, 불필요한 인덱스 식별 및 제거, WiredTiger 압축 기능 활용을 위한 효과적인 전략을 알아보세요. 데이터 아카이빙 구현, oplog 크기 관리, 디스크 공간 사전 모니터링을 통해 시스템 중단을 방지하고 성능을 개선하는 방법을 발견하세요. 이 문서는 MongoDB 배포를 가볍고 효율적으로 유지하기 위한 실행 가능한 통찰력과 실용적인 예제를 제공합니다.
MongoDB 디스크 공간 사용 관리 및 축소를 위한 모범 사례
MongoDB 디스크 사용량은 일반적으로 가장 좋지 않은 시점에 긴급해집니다. 배치 작업이 예상보다 오래 실행되거나, 삭제가 공간을 확보하지 못하는 것처럼 보이거나, 복제 세트 멤버가 볼륨이 거의 가득 찼다고 경고하기 시작할 때입니다. 해결책은 하나의 마법 같은 명령어로 해결되는 경우가 거의 없습니다. 공간이 라이브 데이터, 인덱스, 재사용 가능한 WiredTiger 공간, oplog, 로그 또는 로컬 백업인지 알아야 합니다.
가장 안전한 접근 방식은 먼저 측정하고, 더 이상 존재할 필요가 없는 것을 줄인 후에야 압축이나 멤버 재구축과 같은 더 무거운 유지 관리를 실행하는 것입니다. 이 순서는 공간을 거의 확보하지 못하는 긴 유지 관리 이벤트를 생성하는 것을 방지합니다.
MongoDB 디스크 공간 소비 이해
MongoDB는 여러 구성 요소에 디스크 공간을 사용합니다.
- 데이터 파일: 컬렉션 내의 실제 BSON 문서를 저장합니다.
- 인덱스 파일: 효율적인 쿼리 실행을 지원하기 위해 생성된 B-트리 인덱스를 저장합니다.
- 저널 파일 (WiredTiger): 데이터 파일에 적용되기 전에 쓰기 작업을 기록하여 데이터 내구성을 보장합니다. 사전 할당됩니다.
- Oplog (운영 로그): 모든 쓰기 작업을 기록하는 복제 세트의 특수 고정 컬렉션입니다. 복제에 필수적입니다.
- 진단 데이터: 로그,
mongod프로세스 파일 및 기타 시스템 관련 정보.
시간이 지남에 따라 업데이트, 삭제 및 문서 증가(패딩)로 인해 컬렉션과 인덱스가 조각화되거나 사용되지 않는 할당 공간이 포함되어 비효율적인 디스크 사용이 발생할 수 있습니다. 이 "흰색 공간"은 데이터베이스가 더 이상 라이브 데이터에 필요하지 않더라도 운영 체제에서 즉시 회수되지 않습니다.
MongoDB 디스크 공간 축소 전략
1. 컬렉션 및 인덱스 압축
압축 작업은 데이터 및 인덱스 파일을 더 효율적으로 다시 작성하여 사용되지 않는 디스크 공간을 회수하는 데 도움이 됩니다. 이는 상당한 데이터 삭제 또는 업데이트 후에 특히 유용할 수 있습니다.
컬렉션 압축
WiredTiger 스토리지 엔진(MongoDB 3.2부터 기본값)을 사용하면 compact는 주로 삭제된 문서의 여유 공간을 회수하고 컬렉션 조각 모음을 수행합니다. MMAPv1의 compact 작업처럼 처음부터 컬렉션의 데이터 파일을 다시 빌드하지는 않습니다.
db.runCommand({ compact: "myCollection" })
compact 고려 사항:
compact작업은 리소스를 많이 사용할 수 있으며(CPU, I/O), 특히 대규모 컬렉션의 경우 상당한 시간이 걸릴 수 있습니다. 유지 관리 기간이나 복제 세트의 보조 멤버에서 실행하는 것이 가장 좋습니다.- 디스크 요구 사항 및 잠금 동작은 MongoDB 버전, 스토리지 엔진 및 배포 형태에 따라 다릅니다. 대규모 프로덕션 컬렉션에서 실행하기 전에 정확한 버전에 대한 설명서를 확인하십시오.
- 샤드 클러스터의 경우 각 샤드에서 독립적으로
compact를 실행하십시오.
인덱스 재구축
인덱스도 조각화될 수 있습니다. 인덱스를 재구축하면 공간을 회수하고 잠재적으로 쿼리 성능을 향상시킬 수 있습니다.
db.myCollection.reIndex()
reIndex() 고려 사항:
reIndex()동작은 MongoDB 버전에 따라 변경되었으며, 여전히 사용량이 많은 시스템에서 중단을 일으킬 수 있습니다. 버전에 대한 매뉴얼을 확인하고, 스테이징에서 테스트하고, 가능하면 복제 세트 멤버를 통해 롤링 작업을 선호하십시오.compact와 유사하게reIndex()는 작업 중에 추가 디스크 공간이 필요합니다.
repairDatabase (오프라인 작업)
심각한 조각화 또는 데이터 손상의 경우 repairDatabase는 모든 데이터 파일을 다시 빌드할 수 있습니다. 이것은 오프라인 작업이며 mongod 인스턴스를 중지해야 합니다.
mongod --repair
경고: repairDatabase는 신중하게 처리하지 않으면 파괴적인 작업이고 매우 오래 걸릴 수 있으므로 공간 회수를 위한 최후의 수단으로 사용해야 합니다. 항상 백업을 보유하십시오.
2. 인덱스 최적화
인덱스는 성능에 중요하지만 상당한 디스크 공간을 소비할 수 있습니다. 사용되지 않거나 중복된 인덱스는 순수한 오버헤드입니다.
불필요한 인덱스 식별 및 제거
정기적으로 인덱스를 검토하여 여전히 필요한지 확인하십시오.
- 컬렉션의 모든 인덱스 나열:
db.myCollection.getIndexes()
```
2. 인덱스 사용량 모니터링: $indexStats, 쿼리 계획, 프로파일링 및 애플리케이션 워크로드 기록을 사용하십시오. 컬렉션 통계는 인덱스 크기를 보여주지만 인덱스가 유용한지 증명하지는 않습니다.
3. 중복 또는 중복 인덱스 식별: 예를 들어 { a: 1, b: 1 }에 대한 인덱스는 복합 인덱스를 사용할 수 있는 쿼리에 대해 { a: 1 }에 대한 인덱스를 중복으로 만듭니다. { a: 1, b: 1 }에 대한 인덱스는 a와 b만 관련된 쿼리의 경우 { a: 1, b: 1, c: 1 }에 대한 인덱스로도 처리됩니다.
식별되면 사용하지 않는 인덱스를 삭제하십시오.
db.myCollection.dropIndex("indexName")
팁: 프로덕션에 적용하기 전에 항상 스테이징 환경에서 인덱스 삭제의 영향을 테스트하십시오.
부분 인덱스 사용
부분 인덱스는 지정된 필터 표현식을 충족하는 컬렉션의 문서만 인덱싱합니다. 이렇게 하면 인덱싱되는 문서 수가 줄어들어 디스크 공간이 절약되고 쓰기 성능이 향상됩니다.
db.orders.createIndex(
{ customerId: 1, orderDate: -1 },
{ partialFilterExpression: { status: "active" } }
)
이 인덱스는 status가 "active"인 문서만 포함하므로 대부분의 주문이 기록, 취소, 보관되었거나 핫 경로 외부에 있는 경우 크기가 줄어듭니다. 중요한 부분은 "active"라는 단어가 아니라 애플리케이션이 매일 실제로 쿼리하는 하위 집합을 인덱싱하는 습관입니다.
정리 명령이 아닌 디스크 공간 분류로 시작하십시오
MongoDB 디스크 공간이 증가할 때 첫 번째 실수는 compact, repair 또는 이전 데이터 삭제로 바로 건너뛰는 것입니다. 이러한 작업은 도움이 될 수 있지만 로드를 생성하거나, 일부 상황에서 잠금을 유발하거나, 몇 주 동안 실제 문제를 숨길 수 있습니다. 세 가지 질문에 답하는 것으로 시작하십시오.
- 어떤 파일 시스템이 가득 차고 있습니까? 데이터베이스 경로, 저널 경로, 로그 경로 또는 백업 볼륨?
- 라이브 데이터가 증가하고 있습니까, 아니면 삭제 및 업데이트 후에 할당되었지만 사용되지 않은 공간이 증가하고 있습니까?
- 증가가 컬렉션, 인덱스, oplog, 로그, 진단 데이터 또는 스냅샷에서 오고 있습니까?
빠른 첫 번째 패스는 일반적으로 다음과 같습니다.
df -h
du -h --max-depth=1 /var/lib/mongodb | sort -h
du -h --max-depth=1 /var/log/mongodb | sort -h
그런 다음 셸 내부에서 MongoDB를 확인하십시오.
db.adminCommand({ listDatabases: 1 })
db.getSiblingDB("app").stats()
db.getSiblingDB("app").orders.stats()
storageSize, totalIndexSize 및 dataSize는 다른 이야기를 들려줍니다. dataSize가 증가하고 있다면 데이터 수명 주기 문제가 있을 수 있습니다. storageSize가 dataSize보다 훨씬 크다면 삭제 후 재사용 가능한 내부 공간을 보고 있을 수 있습니다. totalIndexSize가 dataSize에 비해 크다면 압축을 건드리기 전에 인덱스 설계에 주의를 기울여야 합니다.
MongoDB가 무엇을 되돌려줄 수 있고 되돌려줄 수 없는지 이해하십시오
WiredTiger를 사용하면 문서를 삭제하면 일반적으로 MongoDB에서 재사용할 수 있는 공간이 생깁니다. 항상 즉시 운영 체제에 공간을 반환하지는 않습니다. 이 동작은 긴급 정리 중에 사람들을 놀라게 합니다. 대규모 배치를 삭제하고 df -h를 실행하면 거의 개선되지 않습니다.
삭제가 실패했다는 의미는 아닙니다. MongoDB가 향후 삽입 및 업데이트를 위해 해당 공간을 재사용할 수 있는 경우가 많다는 의미입니다. 목표가 성장을 멈추는 것이라면 이전 데이터를 삭제하거나 보관하는 것만으로 충분할 수 있습니다. 목표가 볼륨이 거의 가득 찼거나 호스트 크기가 축소되어 파일 시스템을 축소하는 것이라면 압축, 복제 세트 멤버 재동기화 또는 덤프 및 복원 스타일 재구축이 필요할 수 있습니다.
프로덕션 시스템의 경우 일반적으로 작업을 두 개의 트랙으로 분리합니다. 첫 번째 트랙은 즉각적인 안전입니다. 디스크 추가, 명백한 로그 축적 제거, 위험한 배치 작업 일시 중지 또는 데이터베이스 볼륨에서 백업 이동. 두 번째 트랙은 실제 축소입니다. 보존 수정, 사용하지 않는 인덱스 제거, 바이트가 어디로 갔는지 확인한 후에만 스토리지 재구축.
조각 모음 전에 데이터 보존 수정
애플리케이션이 요청 로그, 이벤트, 세션, 알림, 작업 레코드 또는 분석 문서를 영원히 유지하는 경우 아무리 조심스럽게 압축해도 디스크 사용량이 돌아옵니다. MongoDB는 몇 가지 실용적인 옵션을 제공합니다.
단순한 타임스탬프로 만료되는 데이터의 경우 TTL 인덱스가 가장 깔끔한 답인 경우가 많습니다.
db.sessions.createIndex(
{ expiresAt: 1 },
{ expireAfterSeconds: 0 }
)
해당 인덱스는 expiresAt에 저장된 날짜 이후에 문서를 제거합니다. 세션, 임시 토큰, 수명이 짧은 가져오기 작업 또는 캐시된 API 응답에 유용합니다. 비즈니스 보존 규칙을 대체하지는 않습니다. TTL 모니터는 백그라운드에서 실행되므로 초 단위 삭제를 기대하지 말고 삭제 전에 승인 워크플로가 필요한 데이터에 TTL을 사용하지 마십시오.
비즈니스 레코드의 경우 무턱대고 삭제하는 대신 보관하십시오. 일반적인 패턴은 다음과 같습니다.
- 보존 기간보다 오래된 문서를 더 저렴한 스토리지 또는 아카이브 데이터베이스에 복사합니다.
- 개수 및 중요한 필드 샘플을 확인합니다.
- 기본 컬렉션에서 작은 배치로 삭제합니다.
- 작업이 실행되는 동안 복제 지연 및 디스크 메트릭을 관찰합니다.
작은 배치가 중요합니다. 단일 대규모 삭제는 복제 압력을 생성하고, 로그를 채우고, 필터가 잘못되었다는 것을 누군가가 깨달았을 때 롤백을 더 어렵게 만들 수 있습니다. 더 안전한 배치 작업은 한 번에 수천 개의 문서를 삭제하고, 잠시 멈추고, _id 또는 타임스탬프로 진행 상황을 기록할 수 있습니다.
while (true) {
const result = db.events.deleteMany({
createdAt: { $lt: ISODate("2025-01-01T00:00:00Z") },
archived: true
});
print(`deleted ${result.deletedCount}`);
if (result.deletedCount === 0) break;
sleep(500);
}
실제 프로덕션 스크립트에서는 전체 범위에 대해 deleteMany 대신 제한 패턴을 추가하고, 각 배치를 기록하고, 복제 지연 또는 디스크 I/O가 임계값을 초과하면 자동으로 중지하십시오.
너무 단순해 보이는 인덱스 조언에 주의하십시오
사용하지 않는 인덱스를 삭제하는 것은 MongoDB 디스크 공간을 줄이는 가장 좋은 방법 중 하나이지만 "사용되지 않음"에는 컨텍스트가 필요합니다. 인덱스는 조용한 주 동안 사용되지 않는 것처럼 보일 수 있지만 월말 보고서, 백그라운드 조정 또는 드문 고객 지원 워크플로에 여전히 중요할 수 있습니다.
$indexStats를 사용하여 액세스 패턴을 확인하십시오.
db.orders.aggregate([{ $indexStats: {} }])
그런 다음 결과를 애플리케이션 코드, 예약된 작업, 대시보드 및 지원 쿼리와 비교하십시오. 마지막 재시작 이후 인덱스가 사용되지 않았다면 그것은 신호일 뿐, 평결은 아닙니다. 삭제하기 전에 서버가 최근에 재시작되었는지와 워크로드 샘플에 중요한 작업이 포함되어 있는지 확인하십시오.
또한 겹치는 복합 인덱스를 주시하십시오. 다음과 같은 경우:
{ customerId: 1 }
{ customerId: 1, createdAt: -1 }
{ customerId: 1, createdAt: -1, status: 1 }
하나를 제거할 수 있지만 정렬 순서, 쿼리 필터 및 더 짧은 인덱스가 다른 액세스 패턴을 지원하는지 확인한 후에만 가능합니다. MongoDB는 복합 인덱스의 왼쪽 접두사를 사용할 수 있지만 가장 큰 인덱스가 항상 무료 대체품이라는 의미는 아닙니다. 더 큰 인덱스는 더 많은 메모리와 쓰기 I/O를 소비하므로 가장 완벽해 보이는 인덱스가 아니라 워크로드에 맞는 인덱스를 유지하십시오.
복제 세트의 대규모 축소 작업에는 재동기화 선호
대규모 복제 세트의 경우 운영 체제 디스크 공간을 회수하는 가장 깔끔한 방법은 종종 한 번에 하나의 보조를 재구축하는 것입니다. 기본 아이디어는 다음과 같습니다.
- 건강한 복제 및 최신 백업이 있는지 확인하십시오.
- 보조를 제거하거나 중지하십시오.
- 로컬 데이터 디렉토리를 지우십시오.
- 기본 또는 다른 건강한 멤버에서 다시 동기화하도록 하십시오.
- 다음 보조에 대해 반복하십시오.
- 유지 관리 기간 동안 기본을 강등시키고 마지막으로 이전 기본을 재구축하십시오.
이 접근 방식은 명령을 실행하는 것보다 느리지만 각 재구축된 멤버가 현재 데이터를 기반으로 새 스토리지 파일을 쓰기 때문에 추론하기가 더 쉽습니다. 또한 프로덕션 트래픽에서 모든 컬렉션을 압축하려고 시도하지 않습니다. 무료는 아닙니다. 초기 동기화는 네트워크 및 디스크 집약적일 수 있으며 한 멤버가 재구축되는 동안 복제 세트를 안전하게 유지하기에 충분한 나머지 멤버가 필요합니다.
독립형 MongoDB 서버의 경우 해당 이점이 없습니다. 이 경우 유지 관리 기간을 계획하고, 테스트된 백업을 수행하고, mongodump/mongorestore 또는 새 볼륨으로의 파일 시스템 수준 마이그레이션을 고려하십시오. 더 작은 데이터 디렉토리를 원한다고 해서 mongod --repair를 선택하지 마십시오. 복구를 일상적인 유지 관리가 아닌 복구 도구로 취급하십시오.
Oplog, 로그 및 백업도 확인
모든 MongoDB 디스크 압력이 컬렉션에서 오는 것은 아닙니다. 복제 세트에서 oplog는 고정 컬렉션이므로 영원히 커져서는 안 되지만 구성된 크기는 여전히 중요합니다. 너무 작으면 유지 관리 중에 보조가 떨어질 수 있습니다. 작은 디스크에서 필요한 것보다 훨씬 크면 공간을 낭비할 수 있습니다. 신중하게 검토하십시오.
db.getSiblingDB("local").oplog.rs.stats()
느린 쿼리 로깅, 디버그 상세도 또는 애플리케이션 오류 루프가 시끄러워지면 MongoDB 로그도 디스크를 채울 수 있습니다. 로그 순환을 사용하고 가능하면 데이터베이스 로그를 데이터를 저장하는 동일한 작은 볼륨에서 멀리 유지하십시오.
백업은 또 다른 일반적인 놀라움입니다. 팀은 편리하기 때문에 동일한 호스트에 mongodump를 실행한 다음 백업 기간 동안 디스크 경보가 울리는 이유를 궁금해합니다. 동일한 파일 시스템에 저장된 백업은 그다지 백업이 아니며 이미 위험한 작업 중에 MongoDB를 더 나쁜 중단 상태로 밀어넣을 수 있습니다. 백업을 객체 스토리지, 백업 서버 또는 별도의 마운트된 볼륨으로 스트리밍하십시오.
가득 찬 MongoDB 디스크에 대한 실용적인 런북
디스크가 이미 90% 이상인 경우 속도를 늦추고 다음 순서로 작업하십시오.
- MongoDB가 여전히 쓰기를 수락하고 복제 세트가 정상인지 확인하십시오.
- 플랫폼에서 허용하는 경우 임시 디스크 용량을 추가하십시오. 이는 종종 긴급 삭제보다 안전합니다.
- 크기가 큰 로그 및 로컬 백업 파일을 이동하거나 순환시키십시오.
- 많이 쓰고 있는 중요하지 않은 배치 작업을 중지하십시오.
db.stats()및 컬렉션stats()를 사용하여 가장 큰 컬렉션과 인덱스를 식별하십시오.- 명확한 보존 규칙이 있는 데이터만 보관하거나 삭제하십시오.
- 시스템이 안정된 후 압축, 재동기화 또는 복원을 계획하십시오.
최고의 장기적인 해결책은 지루합니다. 보존 규칙, 인덱스 검토, 디스크 경보 및 테스트된 재구축 절차입니다. MongoDB는 내부 여유 공간을 재사용하는 데 편안하지만 운영자는 여전히 어떤 데이터가 빠른 스토리지에 저장될 가치가 있고 어떤 데이터가 다른 곳으로 이동할 수 있는지 결정해야 합니다.