DEVELOPMENT/DB

[MongoDB] Building with Patterns

heeble 2023. 11. 1. 21:20
본 문서는 "MongoDB Developer Center Articles"를 참고하여 작성되었습니다.
🔗 https://www.mongodb.com/developer/products/mongodb/polymorphic-pattern/

 

 

The Polymorphic Pattern

  • 모든 컬렉션 문서가 유사하지만 완전히 동일하지 않은 구조를 가지고 있을 때
  • 문서가 동일한 컬렉션에 있더라도 각 선수에 대한 저장된 데이터가 동일할 필요는 없음
{
  "sport": "ten_pin_bowling",
  "athlete_name": "Earl Anthony",
  "career_earnings": { value: NumberDecimal("1441061"), currency: "USD"},
  "300_games": 25,
  "career_titles": 43,
  "other_sports": "baseball"
},
{
  "sport": "tennis",
  "athlete_name": "Martina Navratilova",
  "career_earnings": { value: NumberDecimal("216226089"), currency: "USD"},
  "event": {
  	"type": "singles",
    "career_tournaments": 390,
    "career_titles": 167
  }
}

 

The Shema Versioning Pattern

  • MongoDB가 서로 다른 형태의 문서를 동일한 데이터베이스 컬렉션에 존재할 수 있도록 지원하는 특징을 활용
  • 동일한 필드에 대해 서로 다른 필드 또는 서로 다른 필드 유형을 가진 문서가 공존할 수 있음
{
  "_id": "<ObjectId>",
  "name": "Anakin Skywalker",
  "home": "503-555-0000",
  "work": "503-555-0010"
},
{
  "_id": "<ObjectId>",
  "name": "Anakin Skywalker",
  "home": "503-555-0100",
  "work": "503-555-0110",
  "mobile": "503-555-0120"
},
{
  "_id": "<ObjectId>",
  "schema_version": "2",
  "name": "Anakin Skywalker (Retired)",
  "contact_method": [
  	{ "home": "503-555-0210" },
  	{ "work": "503-555-0220" },
    { "twitter": "@anakinskywalker" },
    { "skype" : "AlwaysWithYou" }
  ]
}

 

The Attribute Pattern

다음과 같은 경우에 적합

  • 큰 문서가 많은 유사한 필드를 가지고 있지만 일부 필드는 공통 특성을 공유하며 해당 필드의 하위 집합에서 정렬 혹은 쿼리를 수행
  • 정렬해야 하는 필드가 문서의 작은 하우 집합에서만 발견
  • 문서 내에서 위의 두 가지 조건이 모두 충족되는 경우

➡️ 하위 집합에서 정렬 혹은 쿼리가 수행되는 경우 성능을 최적화하기 위해 모든 하위 집합을 고려하는 많은 인덱스가 발생할 수 있으나 이것은 오히려 성능을 저하시킬 수 있음

// ***************** Before patterning
{
    title: "Star Wars",
    director: "George Lucas",
    ...
    release_US: ISODate("1977-05-20T01:00:00+01:00"),
    release_France: ISODate("1977-10-19T01:00:00+01:00"),
    release_Italy: ISODate("1977-10-20T01:00:00+01:00"),
    release_UK: ISODate("1977-12-27T01:00:00+01:00"),
    ...
},
// ***************** Attribute Pattern
{
    title: "Star Wars",
    director: "George Lucas",
    ...
    releases: [
        {
        location: "USA",
        date: ISODate("1977-05-20T01:00:00+01:00")
        },
        {
        location: "France",
        date: ISODate("1977-10-19T01:00:00+01:00")
        },
        {
        location: "Italy",
        date: ISODate("1977-10-20T01:00:00+01:00")
        },
        {
        location: "UK",
        date: ISODate("1977-12-27T01:00:00+01:00")
        },
        ...
    ],
    ...
}
// Indexing may be like...
{ "releases.location": 1, "releases.date": 1}

 

The Bucket Pattern

  • 사물 인터넷(IoT), 실시간 분석 또는 일반적으로 시계열 데이터와 작업할 때 효과적
  • 데이터를 함께 묶음으로써 특정 데이터 그룹을 조직하는 것이 더 쉬워짐
// Data Example
{
  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
}
/// Wind Up
{
  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
    }
  ],
  transation_count: 42,
  sum_temperature: 2413
}

 

The Outlier Pattern

  • 일반 패턴과 다른 데이터가 있는 경우
// 일반적인 패턴
{
  "_id": ObjetId("507f1f77bcf86cd79943901"),
  "title": "A Genealogical Record of a Line of Alger",
  "author": "Ken W. Alger",
  ...,
  "customers_purchased": ["user00", "user01", "user02"]
}
// costomers_purchased의 리밋이 setting 값을 넘어선 경우
{
  "_id": ObjetId("507f1f77bcf86cd79943901"),
  "title": "A Genealogical Record of a Line of Alger",
  "author": "Ken W. Alger",
  ...,
  "customers_purchased": ["user00", "user01", "user02", ..., "user999"],
  "has_extras": "true"
}

 

The Computed Pattern

  • 애플리케이션에서 반복적으로 계산해야 하는 데이터가 있는 경우에 활용(매 시간 1,000,000 번의 읽기 && 1,000번의 쓰기)

 

The Subset Pattern

  • 작업 세트의 데이터와 인덱스가 할당된 물리적 RAM을 넘어설 때 성능 저하 발생, 디스크 액세스가 발생하고 데이터가 RAM에서 밀려남
  • Option1: 서버에 더 많은 RAM을 추가 -> 한계 존재 
  • Option2: 컬렉션을 샤드로 분할 -> 준비되지 않은 추가 비용과 복잡성 수반
  • Option3: 작업 세트의 크기를 줄이는 것 : Subset Pattern

++ Example ++

[ Product Collection ]

- Only keep the ten most reent reviews

[ Review Collection ]

- Additional Information(Reviews) 

- can be accessed if the user wants to see additional reviews

 

The Extended Reference Pattern

  • 자주 엑세스되는 데이터를 모으기 위해 많은 Join 연산이 필요한 경우

++  Example ++

- 전자 상거래 애플리케이션에서 주문, 고객, 재고는 별개의 논리적 엔터티

- 특정 주문에 대한 정보를 모아야 하는 경우 문제가 발생할 수 있음 -> 한 고객이 N개의 주문을 가질 수 있어 1-N 관계 성립

- JOIN 연산을 줄이기 위해 각 주문에 대한 모든 고객 정보를 중복으로 포함하는 것은 많은 중복 정보를 초래할 수 있음

- 고객에 대한 모든 정보를 저장하는 대신 자주 액세스하는 필드만 복사

 

The Approximation Pattern

  • 정확한 값이 아니라 '충분한' 데이터가 허용이 될 때 ex) 정확한 주민수 보다 약 39,000 명 정도로 충분할 때
  • 데이터베이스의 인구를 모든 변경 사항마다 업데이트하는 대신 카운터를 구현하여 100번마다 1%의 확률로 업데이트 -> 쓰기작업 99% 감소

The Tree Pattern

  • 데이터를 결합해야 하는 경우가 계층적일 때 (EX: 직원부터 CEO 까지의 보고 체인 식별)
  • 부모 노드, 자식 노드를 나열하는 경우는 흔한 방ㅂ버이지만 여러 번의 액세스가 필요할 수 있음

- 대안으로 노드에서 계층 구조의 상위로 이르는 전체 경로 저장 가능

- 데이터의 중복이 발생하고, 정보가 상대적으로 불변인 경우 관리가 쉬우나 기업 구조와 같이 상황이 재조정될 수 있는 경우 필요에 따라 계층을 업데이트 해야하지만 그럼에도 항상 트리를 계산하는 것보다 적은 비용임

 

The Pre-Allocation Pattern

  • 구조가 알려진 경우 구조를 채우거나 확장 가능성이 디자인을 훨씬 간단하게 만들 수 있음
  • 나중에 채울 초기 빈 구조를 생성하도록 지시

One dimensional representation of venue, accessible seats shown in blue

 

two dimensional representation of venue, valid seats available in green. Accessible seating notated with a blue outline

 

The Document Versioning Pattern

  • 일부 문서의 이전 버전을 유지하고 싶을 때
  • 각 문서에 문서 버전을 추적할 수 있게 해주는 필드를 추가

[ 데이터 액세스 패턴의 가정 ]

- 각 문서에는 너무 많은 리비전이 존재하지 않는다.

- 버전을 생성해야 하는 문서가 너무 많지 않다.

- 대부분의 쿼리가 문서의 가장 최신 버전에서 수행된다.