티스토리 뷰

Database

[MongoDB] Schema Design Pattern

집사킴 2023. 1. 21. 10:55
728x90

Schema Design Pattern

데이터 모델링 시 자주 나타나는 과제들을 해결하기 위한 방법들을 비슷한 특징끼리 묶어 정리한 것

디자인 패턴의 데이터 모델링 버전이라고 볼 수 있다

소프트웨어 개발 방법에서 사용되는 디자인 패턴은 프로그램 개발에서 자주 나타나는 과제를 해결하기 위한 방법 중 하나로, 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 이름을 붙여, 이후에 재이용하기 좋은 형태로 특정의 규약을 묶어서 정리한 것이다. 알고리즘과 같이 프로그램 코드로 바로 변환될 수 있는 형태는 아니지만, 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 준다. - 위키피디아

 

사실 MongoDB만을 위한 패턴은 아니다. 다만 유연한 스키마를 가진 MongoDB에서 사용하기에 효과적이다.

은총알은 없다. 나에게 주어진 use case에 꼭 맞는 패턴이 없을 가능성이 더 높다. 여기서 나오는 패턴들을 그대로 갖다 쓸 순 없고 요구사항에 맞게 조합과 변형이 필요하다.

 

스키마 디자인 전 측정이 필요한 항목들

  1. 데이터의 스케일이 어느정도인지 (Scale it can expect.)
  2. 비즈니스 로직이 읽기/쓰기 중 어느 쪽에 더 빈도가 높은지 (Whether the use-case is Write or Read intensive.)
  3. 데이터베이스 운용 비용이 어느정도 들지 (Cost on the Database.)

 

패턴 종류

(몽고디비 공식 블로그에서 소개하는 12개의 패턴 중 5개 패턴만 훑어보겠습니다)


Computed pattern

  • 조회 시점에 매번 계산하지 않고 미리 계산된 데이터를 저장하는 방식
  • 읽기 부하를 줄일 수 있지만 쓰기 부하가 증가한다
  • ex) 영화 상세페이지에 리뷰 수를 표시해야 할 경우, 매번 리뷰데이터의 count를 하지 않고 영화 컬렉션에 total_count값을 미리 저장해 두는 것
    • 장점 : 계산빈도가 낮아져 cpu와 불필요한 인덱스 절약 가능
    • 단점
      • 새 리뷰 달릴 때마다 total_count를 업데이트 해줘야함.
      • → 쓰기 부하 늘지만 읽을 때마다 count 계산하는 것보단 빈도가 낮음
      • 데이터 무결성 관리 필요
      • → total_count의 정확성이 비즈니스에 중요한 부분은 아니기 때문에 필요시 다시 계산하면 됨

 

Extended Reference pattern

  • 다른 컬렉션의 데이터를 가져와서 저장하는 것 (=역정규화)
  • 빠른 읽기가 목적일 경우, $lookup(join)으로 2번 조회하는 것보다는 이 패턴을 사용하여 1번만 조회하는 것이 좋을 수 있음

 

Bucket pattern

  • IoT 스트리밍, 실시간 데이터 분석, 시계열 데이터에 효과적으로 사용 가능
  • 여러 도큐먼트를 묶어서 하나의 도메인 오브젝트로 관리
  • max bucket size를 정해야 함
// 온도 센서에서 1분마다 온도데이터를 받아오는 경우

// before : 데이터를 도큐먼트 단위로 받음
{
   sensor_id: 12345,
   timestamp: ISODate("2019-01-31T10:00:00.000Z"),
   temperature: 40
}

{
   sensor_id: 12345,
   timestamp: ISODate("2019-01-31T10:01:00.000Z"),
   temperature: 40
}

{
   sensor_id: 12345,
   timestamp: ISODate("2019-01-31T10:02:00.000Z"),
   temperature: 41
}

// after : measurements 필드 안에 subset으로 온도 데이터를 저장
{
    sensor_id: 12345,
    start_date: ISODate("2019-01-31T10:00:00.000Z"),
    end_date: ISODate("2019-01-31T10:59:59.000Z"),
    measurements: [
       {
       timestamp: ISODate("2019-01-31T10:00:00.000Z"),
       temperature: 40
       },
       {
       timestamp: ISODate("2019-01-31T10:01:00.000Z"),
       temperature: 40
       },
       … 
       {
       timestamp: ISODate("2019-01-31T10:42:00.000Z"),
       temperature: 42
       }
    ],
   transaction_count: 42,
   sum_temperature: 2413
}

 

Outlier pattern

  • 일반적이지 않은 데이터 패턴에 대한 최적화 작업을 나중에 하는 것
  • 소셜미디어에서 수많은 팔로워를 보유한 소수의 셀럽 정보, 수많은 책들 중 소수의 베스트셀러 서적 정보 등 일반적인 범위를 초과한 데이터에 대한 최적화 처리
  • 일반적인 범위 초과 시 overflow라 불리는 다른 컬렉션에 데이터를 보관
// 일반적인 책 정보 스키마
{
    "_id": ObjectID("507f1f77bcf86cd799439011")
    "title": "A Genealogical Record of a Line of Alger",
    "author": "Ken W. Alger",
    …,
    "customers_purchased": ["user00", "user01", "user02"]
	// customers_purchased라는 버킷에 구매고객 데이터 저장

}

// 구매자가 1000명을 넘는 베스트셀러일 경우
{
    "_id": ObjectID("507f191e810c19729de860ea"),
    "title": "Harry Potter, the Next Chapter",
    "author": "J.K. Rowling",
    …,
   "customers_purchased": ["user00", "user01", "user02", …, "user999"],
   "has_extras": "true"
	// customers_purchased의 max bucket size를 999로 놓고, 초과 시 'has_extras' flag를 추가
}

 

Bucket pattern vs Outlier

bucket pattern : 초과 데이터를 bucket에 보관하는 경우

  • 다른 버킷에 대한 pk가 버킷 수만큼 생김

outlier pattern : 초과 데이터를 overflow에 보관하는 경우

  • bucket에 array로 들어간 데이터들을 도큐먼트 단위로 보관한다
  • overflow의 수 만큼 pk가 생김

 

Approximation pattern

  • 원래 데이터의 근사치를 따로 저장해 두는 방식
  • 쓰기 부하가 크면서 정확도가 중요하지 use case에서 효과적
    • ex) 페이지 방문자 수 집계

실제 사례 : 근사치 값 저장용 컬렉션을 따로 두었음. page_views라는 하나의 도큐먼트에서 count를 관리.

0~99의 값 중 랜덤값을 생성하여 그 값이 0일 때만 +100을 함

cpu 부하 90%에서 5~10%로 감소시킴


참고자료

https://www.mongodb.com/blog/post/building-with-patterns-a-summary

https://www.youtube.com/watch?v=bxw1AkH2aM4 

https://shanu95.medium.com/schema-patterns-mongodb-part-1-16564f1198dc

728x90

'Database' 카테고리의 다른 글

Redis DataType 간단 정리  (1) 2023.05.13
[MongoDB] BSON(Binary JSON)  (0) 2023.01.23
[MongoDB] 샤딩 전략 - Ranged Sharding, Hash Sarding, Zone Sharding  (0) 2023.01.19
[MongoDB] Sharded Cluster  (0) 2023.01.17
[MongoDB] Replica Set  (0) 2023.01.15
댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함