도큐먼트 크기
- 아주 빈번하게 변경되는 데이터만 분리하는 것은 안정적 서비스를 위해 고려해볼 만하다.
- 기능별로 조회되는 부분이 완전히 다르다면 (액세스 패턴이 다르다면) 분리하는 것도 좋은 방법이다.
- 각 필드를 그룹핑해서 서브 도큐먼트를 만들고 응용프로그램에서 필요 서브도큐먼트만 선별해서 가져가는 것이 네트워크 사용량을 줄이는데 도움이 될 것이다.
(뒤에 조금 더 자세히 설명한다.)
정규화(Document Referencing) vs 역정규화(Embedding)
- 역정규화는 데이터가 얼마나 커지는지, 데이터를 어떻게 읽어가는지에 따라 할지 말지 결정해라.
- 가능하면 몽고DB도 정규화를 사용하라. join이 안된다고 Embedding을 먼저 생각하지는 말자.
서브 도큐먼트
- 데이터를 성격별로 묶어서 그룹핑하는 것도 고려하자.
- 서브 도큐먼트 없이 일반 필드로만 구성
{ _id: 1, user_name: "matt.lee", user_real_name: "SeongUck Lee", contact_office_number: "010-xxxx-xxxx", contact_house_number: "02-xxx-xxxx", address_zip_code: "00000", address_detail:"ABC Apt Seongsu-1ga", address_city: "Seoul", address_country: "Korea", ... }
- 서브 도큐먼트로 필드 그룹
{ _id: 1, user_name: "matt.lee", user_real_name: "SeongUck Lee", contact: { office_number: "010-xxxx-xxxx", house_number: "02-xxx-xxxx" }, address: { zip_code: "00000", detail: "ABC Apt Seongsu-1ga", city: "Seoul", country: "Korea" }, ... }
- 다음과 같은 장점이 있다.
- 도큐먼트의 가독성과 식별성을 높여줄 수 있다.
- 필드의 이름에서 반복된 단어를 생략할 수 있다.
- 미세하지만 성능적인 장점도 얻을 수 있다.
인덱스
- 인덱스는 가능하면 "ESR" Rule대로 만들자(E:Equal, S:sort, R:range)
- 불필요한 인덱스는 만들지 말자. 인덱스 생성으로 인해 느려질 수 있다.
- 몽고의 Sort는 메모리에서 일어나며 sort를 위해 일반적으로 32mb의 공간만 할당하고 있다. 즉 32mb 이상을 읽어서 sort하면 에러가 발생한다. 이런 이유로 sort는 index를 이용하는 것을 추천한다.
배열
- 제한 없이 증가하는 데이터면 사용하지 말 것.
- 배열 관련 연산자는 $push, $pop이 성능상 좋다. $addToSet이나 $pull 연산이 빈번한 모델이면 배열 타입 사용은 한 번 더 고민해보자.
- 배열이 너무 크면 oplog 생성으로 인한 부하가 크다. 배열 사이즈는 적당히 유지되어야 한다.
필드 이름
- 데이터양이 아주 많은 경우 긴 필드이름은 성능에 영향을 미칠 수 있다.
도큐먼트 유효성
- 몽고DB는 컬렉션에 속한 필드 값에 대해서는 기본적으로 어떠한 제약도 가지지 않지만 필요시 RDBMS에서와 같은 정규화된 제약을 설정할 수 있다.
- 유효성 체크 규칙은 컬렉션 생성할 때 뿐만 아니라 이미 사용되고 있는 컬렉션에 대해서도 설정 가능하다.
조인
- 몽고DB는 기본적으로 조인을 지원하지 않았으나 3.2 버전부터는 $lookup이라는 보조적인 조인 기능을 제공한다.
- 하지만 몇 가지 제약사항이 있다.
- INNER JOIN은 지원하지 않으며, OUTER JOIN만 지원한다.
- 조인되는 대상 컬렉션은 같은 데이터베이스에 있어야 한다.
- 샤딩되지 않은 컬렉션만 "$lookup" 오퍼레이션을 사용할 수 있다.
[출처]
대용량 데이터 처리를 위한 Real MongoDB / 위키북스 / 이성욱 지음