[2023 AWS re:Invent] Data modeling core concepts for Amazon DynamoDB

세션명

Data modeling core concepts for Amazon DynamoDB
(Amazon DynamoDB의 데이터 모델링 핵심 개념)

강연자

Akshat Vig(Sr.Principal Engineer Amazon Web Services), Greg Krumm(Sr.DynamoDB Solutions Architect Amazon Web Services)

핵심 내용 요약
  • DynamoDB Architecture
  • Partition Key
  • How to Optimize the cost of using DynamoDB
  • How can we filter data in DynamoDB?
세션 키워드
  1. Data Modeling
  2. Vertical Partitioning
  3. Global Secondary Indexes
  4. Cost Optimization
  5. Workload Isolation
  6. Sparse Indexes
세션 요약자

베스핀글로벌 PS본부 D&A실 권순정 님

DynamoDB Architecture

DynamoDB Table의 기본 개념

1) 테이블(Table)

AWS 콘솔을 이용해서 이름, 기본키 ,정렬키, 글로벌 보조 인덱스 , 용량 등을 설정해줍니다.
용량을 변경할 수 있지만 이름 및 기본키 등은 변경할 수 없기 때문에 이를 고려해서 만들어야 합니다.

2) 기본키(Partition Key)

Parition Key라고도 하며, SQL의 Primary key와 유사한 개념입니다. 이 키는 고유해야하며, 업데이트를 하거나 쿼리를 할 때 필요합니다.
고유한 키여야 하며, string, number, binary(암호화된 에디터나 복잡한 문자열 등) 타입만 가능합니다.

3) 로컬 보조 인덱스(Local Secondary Index)

파티션 키 및 정렬 키를 합친 복합 인덱스 입니다. 정확한 명칭은 Local Secondary Index입니다.
파티션키와 정렬키를 합친 것이며 동일한 파티션 키 내에서 정보들을 분리하고 싶을 때 사용합니다. 로컬 인덱스의 경우, 테이블을 만들 떄 미리 설정해두어야 합니다. 한번 설정한 후에는 삭제, 추가 ,수정이 불가능합니다.

4) 글로벌 보조 인덱스(Global Secondary Index)

기본키나 정렬키와는 별개로 특정 키를 인덱스 키로 활용할 수 있는 개념입니다.
글로벌 인덱스의 경우, 콘솔에서 해당 테이블을 클릭하면 글로벌 인덱스를 만들 수 있는 탭이 있습니다. 기존의 attribute 중 하나를 선택해 자유롭게 추가, 수정 , 삭제 할 수 있습니다.

How many tables do you need to store the data?

좋은 스키마 디자인은 탄탄한 기초부터 시작하며 집을 짓는 것과 같은 개념이란게 보여집니다.

데이터베이스 설계에서 단일 테이블 또는 다중 테이블 접근 방식 중 하나를 선택하면 특정 워크로드와 우선순위에 따라 유연성을 확보 가능합니다.
한 테이블에서 엔티티의 우선 순위를 함께 지정하면 UI 성능이 향상될 수 있지만 액세스 제어 및 규정 준수에 대한 세심한 고려가 필요합니다.

Multi Table Design

다중 테이블 설계는 기존 관계형 데이터베이스와 마찬가지로 구현이 단순화 되지만 두가지 테이블에 대한 데이터가 필요한 경우 조인에 대한 계산이 들어가야합니다. 또한, 데이터 검색이 중복될 수 있습니다. 올바른 균형을 유지하려면 쿼리 패턴 및 여러 엔티티에 동시에 액세스 해야하는 필요성 등이 고려되야 합니다.

Single Table Design

단일 테이블 디자인의 이점 중 일부는 데이터 지역성이 있다는 점입니다.

모두 동일한 접두사가 있는 새 엔티티에 대한 쿼리를 실행하면 동일한 쿼리에서 해당 엔티티를 가져올 수 있습니다. Dynamodb 의 쿼리 및 스캔 API의 이점 중 하나는 항목을 읽을 때 항목의 전체 크기를 병합하고 4KB 단위로 요금을 청구한다는 점입니다.

따라서 하나의 쿼리에 41KB 항목이 있는 경우 항목이 서로 다르더라도 하나만 읽은 것처럼 요금이 청구 됩니다. 이유는 해당 항목의 RCU 또는 절반인 최종 일관성으로 판명되기 때문입니다. 또 다른 이점은, 공통 테이블의 모든 엔티티에서 공유된다는 것입니다.

따라서, 쓰기 또는 읽기 비율이 매우 낮은 주문이 있지만 읽기 비율이 더 높은 고객이 있는경우 트래픽을 전체 공유됩니다. 그리고 용량이 서로 균등하게 분배되었기 떄문에 용량이 과도하게 프로비저닝 되는것에 대해서 걱정할 필요가 없습니다.

Schema building blocks-patterns for scale

Parition Key

DynamoDB의 스키마 선정시 가장 중요한점은 올바른 파티션키를 선택해야 합니다.
각 파티션을 이 키 공간으로 나눕니다. 중요한 이유는 해시키라고 불리는 파티션키입니다.
이 값을 해싱함수에 전달 . 이것은 반복 가능한 해시 함수이며 특정 서버나 스토리지 노드인 특정파티션에 매핑할수있습니다.
따라서, 동일한 파티션키를 볼때마다 동일한 파티션키를 사용하여 데이터가 어디 위치해있는지 정확하게 알 수있습니다.

Sort-Key

파티션 키는 키 값 조회만 제공합니다.
동일한 파티션 키아래에 그룹화 되기 때문에 전체 파티션을 읽을 필요가 없으며 범위만 읽는 것이 가능합니다.
일반적으로 타임스탬프와 같은 날자씨간의 정렬키로 선택합니다. 정렬키를 이용하여 쿼리 자체를 미세 조정가능합니다.
정렬키가 없다면 단일 고객에 대한 기록, 모든 지불 내역 및 등 전부 기록해야 하기 때문에 품목의 크기가 계속 확장됩니다.
정렬키는 이미지와 같이 주문 ID와 동일하며 하나의 특정 주문을 요청 할 수 있습니다.

How to optimize the cost of using DynamoDB

DynamoDB에서 용량단위(읽기 용량 단위 -RCU 및 쓰기 용량 단위 -WCU)는 처리 중인 항목의 크기에 따라 할당됩니다. DynamoDB 항목 별로 최대 크기 제한이 있으며, 100바이트의 항목이 있을 경우 업데이트 시 또는 권한 작업을 수행 할 때 최대 1024의 RCU 또는 WCU를 소비할 수 있습니다.
예를들어, 400KB 항목은 쓰기시 400 WCU , 읽기시 400 RCU를 소비할 수 있습니다.
DynamoDB에서 더 큰 항목을 처리하면 한 번의 통화로 처리되는 데이터 양이 증가하여 지연 시간이 증가하고 성능이 저하됩니다.
DynamoDB는 처음 스토리지 엔진에서 항목을 찾습니다.

만약에, 약 라인 아이템의 사과,오렌지가 한 attribute로 있을 경우 20KB의 용량을 가진다고 가정해봅시다.
특정 라인 품목의 상태를 업데이트하려면 DynamoDB가 업데이트의 크기 뿐만 아니라 품목의 전체 크기를 기준으로 요금을 부과하는 것이 문제가 되는 상황입니다. 하지만, 특히 자주 업데이트되는 구성 요소를 조금 더 작은 항목으로 분류합니다.

예를들어, 주문상태가 더 자주 업데이트 되는 반면, 고객정보는 상대적으로 정적일 수 있습니다.
라인 아이템이 여러 개(예: 사과,오렌지)인 주문의 경우, 각 라인 아이템은 DynamoDB에 별도의 아이템으로 저장됩니다. 각 아이템은 고객 ID를 메인키로, 주문라인 키를 소트로 연관되며 이제 특정 아이템의 상태를 업데이트시 원래 주문 문서의 전체 20KB가 아닌 업데이트 크기에 대한 비용만 지불합니다.

How can we filter data in DynamoDB?

DyanmoDB에서는 필터링 가능한 방법이 총 3개입니다.

  • 파티션 및 정렬키를 사용한 필터링 : 테이블에 맞는 파티션 키를 선택합니다.
    구성 중인 액세스 패턴 또는 쿼리 패턴에 맞게 올바른 정렬키를 선택합니다. 가장 많이 액세스되는 데이터에 최적화된 스키마를 구축합니다.
  • 보조 인덱스 사용 : 로컬 보조 인덱스 및 글로벌 보조 인덱스를 포함한 보조 인덱스를 활용합니다.
  • 필터 식 : 필터 표현을 사용한 필터링이지만, 테이블 전체를 스캔하는 것과 같은 개념이기 때문에 비용 최적화 포인트 적으로는 필요없는 개념이라고 생각합니다.

Why is it important to choose the primary key of the index?

DynamoDB에서는 Index키를 잘 못 잡을 경우 Hot key 이슈가 발생할 수 있습니다.
기본 테이블의 다른 부분에서 해당 인덱스로 들어가고 결국 클라이언트로 반환되는 기본 테이블에 조절이 발생하게 됩니다.
즉, 애플레케이션 가용성의 문제가 발생하게 됩니다.

우리가 보고 있는 결제날짜에 예에서 앞서 보듯이 귀하의 애플리케이션이 주문 생성시 배송 시점에 결제 날짜를 기록한다고 가정해보겠습니다.
또한, 주문이 배송되고 청구되면 주문에서 결제날짜를 제거하게 됩니다.
그렇다면, pk가 주문 ID이고 정렬키가 결제 날짜인 글로벌 보조 인덱스를 생성할 수 있습니다.
즉, 기본테이블 주문 테이블이 다음과 같다면 결제날짜가 있고 세번째 항목인 ID 3을 볼 경우 이미 배송됐으며 고객에게 요금 청구항목인 결제날짜가 없습니다. 그리고 인덱스에서 일어날일은 실제로 존재하는 두항목만 의미합니다. 주문 id 와 결제날짜만 인덱스를 잡으면 해당 두가지만 인덱스에 표시됩니다.
이는인덱스 저장시 비용을 절감 및 읽기 비용을 줄이는데 도움이 됩니다.
따라서 RCU를 낭비하지 않습니다.

Written by 권 순정 / Soonjung Kwon

Cloud Engineer