티스토리 뷰
Schema Design Pattern
데이터 모델링 시 자주 나타나는 과제들을 해결하기 위한 방법들을 비슷한 특징끼리 묶어 정리한 것
디자인 패턴의 데이터 모델링 버전이라고 볼 수 있다
소프트웨어 개발 방법에서 사용되는 디자인 패턴은 프로그램 개발에서 자주 나타나는 과제를 해결하기 위한 방법 중 하나로, 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 이름을 붙여, 이후에 재이용하기 좋은 형태로 특정의 규약을 묶어서 정리한 것이다. 알고리즘과 같이 프로그램 코드로 바로 변환될 수 있는 형태는 아니지만, 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 준다. - 위키피디아
사실 MongoDB만을 위한 패턴은 아니다. 다만 유연한 스키마를 가진 MongoDB에서 사용하기에 효과적이다.
은총알은 없다. 나에게 주어진 use case에 꼭 맞는 패턴이 없을 가능성이 더 높다. 여기서 나오는 패턴들을 그대로 갖다 쓸 순 없고 요구사항에 맞게 조합과 변형이 필요하다.
스키마 디자인 전 측정이 필요한 항목들
- 데이터의 스케일이 어느정도인지 (Scale it can expect.)
- 비즈니스 로직이 읽기/쓰기 중 어느 쪽에 더 빈도가 높은지 (Whether the use-case is Write or Read intensive.)
- 데이터베이스 운용 비용이 어느정도 들지 (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
'Database' 카테고리의 다른 글
Redis DataType 간단 정리 (0) | 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 |
- Total
- Today
- Yesterday
- mockery
- pods
- devops
- index
- MySQL
- java
- kafka
- 샤딩
- k8s
- Infra
- php
- database
- docker
- laravel 테스트코드
- 분산처리
- 대규모 데이터 처리
- springboot
- mongoDB
- 리눅스 컨테이너
- 라라벨
- 카프카
- JUnit
- phpUnit
- laravel 테스트
- 몽고디비
- 쿠버네티스
- Container
- kubernetes
- NoSQL
- laravel
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |