[MongoDB] 디스크 사용량과 compact
MongoDB는 디스크 사용량에 있어서 꽤나 특이한 입장을 취하고 있다.
"한 번 사용한 디스크 공간은 반환하지 않는다"는 것이다.
그래서 delete를 날려서 데이터를 삭제하더라도 실제로를 삭제하지 않고 여분의 재사용 가능한 공간으로 남겨놓기만 한다. "아무도 쓰지 않고 비어있지만 1TB를 점유하고 있는 테이블"이 존재할 수 있다는 것이다.
RDB들의 경우에는 자동으로 로그 파일을 삭제해서 컴팩트하게 관리되지만 몽고는 그렇지 않다.
얼마나 끔찍한 짓인가...?
사용량 확인해보기
예를 들어서 내 경우에는 -dev 환경이 5기가를 넘게 먹고 있었는데
show dbs

상세히 보면 사용량 패턴이 좀 이상하다.
db.stats()
dataSize는 실제 데이터가 차지하고 있는 영역이고, storageSize가 실제로 차지하고 있는 디스크 영역이다.
실제로 쓰고 있는 공간은 1.5기가 뿐인데 5.6기가를 점유하고 있다는 것이다.
이걸 해결하려면 컬렉션, 데이터베이스를 삭제 후 재생성하거나 compact 명령을 사용해야 한다.
compact 명령
compact는 일종의 디스크 조각 모음을 실행해주는 명령이다. 쓰지 않고 있는 영역을 다 정리하고, 인덱스를 재정렬한다. 하지만 이건 용량을 줄이지 않을 수도 있고, 오히려 공간이 늘어날 수도 있다.
그래서 가장 확실한건 DB를 날리고 옮기는 것이다...
프로덕션 라이브 환경에서는 사용하는게 위험할 수도 있다.
4.4 버전 미만에서는 전체를 차단한 상태에서 실행된다. 4.4 이후의 버전에서도 스키마를 변경하는 동작들은 차단한다.
명령의 사용법은 아래와 같다. 컬렉션명만 넣어주면 된다.
db.runCommand({ compact: 컬렉션명 });
근데 보통 컬렉션 단일로 정리를 할 경우는 많지 않을 것이다.
아래 스크립트는 컬렉션을 전체조회해서 다 compact를 때린다.
db.getCollectionNames().filter(v => v != 'system.views').forEach(function (collectionName) {
print('Compacting: ' + collectionName);
db.runCommand({ compact: collectionName, force:true });
});

참 뭐시기한 정책이 아닐 수 없다.
참조
https://stackoverflow.com/questions/57604139/the-storage-space-isnt-decreased-after-deleting-doc-from-db-why
https://www.mongodb.com/docs/manual/reference/command/compact/
https://stackoverflow.com/questions/7565290/compact-command-not-freeing-up-space-in-mongodb-2-0?rq=4