0. 들어가기 전
이번에 AWS의 DynamoDB를 사용할 기회가 생기게 되었습니다.
이전에 사용해보지 못했던 기술이기 때문에 DynamoDB에 대한 이해가 선행되어야 했습니다.
이번 글에서는 DynamoDB의 적용보다는 DynamoDB의 개념에 대해 알아보고 DynamoDB를 이루는 구성 요소들을 이해하고자 합니다.
그래서 다음과 같은 AWS DynamoDB의 공식문서를 참고하여 글을 작성하면서 DynamoDB를 이해해보겠습니다.
https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/Introduction.html
1. AWS DynamoDB란?
AWS DynamoDB 공식문서에서는 DynamoDB의 특성을 다음과 같은 키워드로 소개하고 있습니다.
Amazon DynamoDB is a serverless, NoSQL, fully managed database with single-digit millisecond performance at any scale.
- Serverless
- NoSQL
- fully managed database :
- single-digit millisecond performance at any scale
해당 키워드들에서 DynamoDB의 특성을 살펴보면 다음과 같습니다.
Serverless
- 서버 관리, 서버 유지보수 비용 없이 사용 가능
- 서버가 없기 때문에 사용한만큼만 비용을 지불하는 On-Demand 모드 사용 가능
NoSQL
- RDB와 달리 Schema가 존재하지 않는 DB
- Key-Value 모델과 Document 모델 모두 지원
- Read Consistency 옵션 제공 (Strongly Read Consistency / Eventually Consistent Read)
- 실시간 데이터 정합성 중요도에 따라 선택 가능
- ACID 트랜잭션 지원 (transactionGetItems, transactionWriteItems)
Good Performance
- 100명이든 1억명이든 상관없이 10ms 미만의 성능 제공 (큰 규모에서도 좋은 성능 제공)
제가 맡은 프로젝트에서는 Serverless, NoSQL의 특성때문에 DynamoDB를 도입했습니다.
- Serverless : 별도의 서버 구축 리소스, 유지보수 리소스가 들지 않고 빠르게 구현 가능
- NoSQL : 적재하려는 데이터가 비정형 데이터에 가까웠기 때문에 Schema 없이 저장가능한 NoSQL 유리
- 추가로, 이미 사내 AWS 인프라가 잘 구성되어 있기때문에 AWS 환경의 Serverless NoSQL인 DynamoDB 도입
2. DynamoDB의 핵심 요소 종류(Core Component)
DynamoDB의 공식 문서에서는 DynamoDB의 핵심 요소를 다음과 같이 언급하고 있습니다.
- Table
- Item
- Attribute
- Primary Key
- Secondary Index
- DynamoDB Streams
이 중에서 Table, Item, Attribute는 기본 DB의 요소와 비슷하기 때문에 간단하게 설명하고 넘어가도록 하겠습니다.
- Table : 다른 DB와 비슷하게 데이터가 저장되는 저장소로, 데이터의 집합이다.
- Item : 다른 DB의 row, record와 비슷한 개념이다.
- Attribute : 다른 DB의 column과 비슷한 개념이다.
Primary Key와 Secondary Index는 다른 DB와 의미상으로는 비슷하지만,
종류 및 구성하는 방법이 다르기 때문에 자세하게 살펴보도록 하겠습니다.
(DynamoDB Streams는 DynamoDB에서 제공하는 변경 데이터 캡쳐(CDC) 부가 기능으로, 여기서는 다루지 않도록 하겠습니다.)
3. Primary Key
DynamoDB의 Primary Key를 살펴보면 다음과 같습니다.
- '테이블의 각 Item을 나타내는 고유 식별자'로 다른 DB와 의미는 같다.
- 하지만, DynamoDB의 Primary Key는 'Partition Key'와 'Sort Key'로 구성된다는 점이 다르다.
여기서 Partition Key와 Sort Key라는 DynamoDB의 Key 2개가 등장합니다.
이를 이해하기 위해서는 우선 DynamoDB의 'Partition' 개념에 대해 이해해야합니다.
3-1. Partition
DynamoDB의 공식문서에서는 Partition을 다음과 같이 소개하고 있습니다.
physical storage internal to DynamoDB
이처럼 Partition은 DynamoDB에서 물리적으로 데이터가 저장되는 스토리지를 의미하는 것을 알 수 있습니다.
이렇게 Partition의 개념에 대해서 인지하고 이제 PK를 구성하는 Partition Key와 Sort Key에 대해서 알아봅시다.
3-2. Partition Key
Partition Key는 이름 그대로 DynamoDB 데이터가 저장되는 스토리지를 구분하기 위한 Key로 이해할 수 있습니다
해당 부분에 대해서 DynamoDB의 공식문서에서는 이를 다음과 같이 언급하고 있습니다.
To write an item to the table, DynamoDB uses the value of the partition key as input to an internal hash function. The output value from the hash function determines the partition in which the item will be stored.
- 테이블에 Item을 Write 시에 DynamoDB는 Partition Key를 사용해서 내부 해시 함수를 호출한다.
- 도출된 해시값으로 Item이 저장될 Partition을 정한다.
즉, Partition Key를 통해 데이터가 저장될 Patition을 결정하는 것을 알 수 있습니다.
해당 설명은 아래 공식문서의 그림을 보면 더 쉽게 이해할 수 있습니다.
해당 그림에서 PK는 다음과 같습니다.
- Partition Key : AnimalType
위의 그림에서 'AnimalType'이 Partition Key로 내부 해시 함수를 호출하여 저장될 Partition을 결정하는 것을 알 수 있습니다.
Partition Key는 이처럼 데이터가 저장될 Partition을 결정하기 때문에 PK 구성 시 필수 요소입니다.
3-3. Sort Key
그렇다면 Sort Key는 무엇이고 왜 존재할까요?
결론부터 말하면, Sort Key는 PK 구성 시 선택 요소입니다.
즉, 필수 요소인 Partition Key에 의해 데이터가 저장될 Partition이 결정되고 이후 복합키 생성 및 정렬 기능을 위해 존재하는 Key입니다.
해당 Sort Key는 다음과 같은 2가지 관점에서 바라볼 수 있습니다.
- PK(복합키)의 의미적인 관점
- Partition 내의 정렬을 수행하는 기능적인 관점
먼저, PK의 의미적인 관점에서 DynamoDB의 공식문서는 다음과 같이 언급합니다.
In a table that has a partition key and a sort key, it's possible for multiple items to have the same partition key value. However, those items must have different sort key values.
- Partition Key와 Sort Key가 있는 Table에서 Partition Key가 같은 데이터가 존재할 수 있지만, 해당 데이터들은 모두 다른 Sort Key를 가져야 한다.
즉, Key 2개로 PK를 구성하는 '복합키'의 관점에서
Partition Key가 같더라도 Sort Key가 달라서 데이터를 고유하게 식별할 수 있어야 한다고 언급하고 있습니다.
다음으로, Partition 내의 정렬을 수행하는 기능적인 관점에서 DynamoDB의 공식문서는 다음과 같이 언급합니다.
All items with the same partition key value are stored together, in sorted order by sort key value.
- Partition Key가 같은 데이터는 Sort Key 값에 의해 정렬되어 같은 Partition에 저장된다.
즉, Partition Key가 같은 데이터일 때 Sort Key에 의해 내부 파티션에서 데이터가 정렬되어 저장되는 것을 알 수 있습니다.
이는 아래 공식문서의 그림을 보면 더 쉽게 이해할 수 있습니다.
해당 그림에서 PK는 다음과 같습니다.
- Partition Key : AnimalType
- Sort Key : Name
위의 그림에서 동그라미 쳐진 Partition을 살펴봅시다.
Partition 안의 Item들은 Partition Key인 AnimalType이 'Dog'으로 같기 때문에 같은 Partition에 저장됩니다.
이때, Sort Key인 Name에 의해 Item들이 정렬되어 저장되는 것을 알 수 있습니다.
이를 통해 같은 Partition Key를 가지는 데이터들은 다른 DB의 인덱스를 사용하는 것처럼
Sort Key에 의해 정렬되어 저장되기 때문에 조회 시에 좋은 성능을 발휘할 수 있게 됩니다.
※ 개인적인 DynamoDB PK 구성 생각
개인적으로 DynamoDB의 PK 구성 방식을 생각해봤을 때,
다른 RDB에서 고유 식별자를 두고자 구성한 AutoIncrement 되는 컬럼이 필요 없다고 생각이 들었습니다.
왜냐하면, AutoIncrement 되는 의미없는 고유 식별자를 두는 순간 DynamoDB의 Sort Key는 필요가 없어지기 때문입니다.
- 해당 AutoIncrement 되는 의미없는 고유 식별자가 중복되지도 않아서 복합키로 구성할 필요가 없다.
- 중복되지 않기 때문에 각자 다른 파티션에 적재되어 파티션 내에서 정렬이 필요하지도 않다.
3-4. Partition Key + Sort Key로 PK 구성 예시
앞서 살펴봤듯이 PK는 다음과 같이 2가지로 구성될 수 있습니다.
- Partition Key
- Partition Key + Sort Key
Partition Key 1개로 PK를 구성하는 경우는 다른 DB와 비슷한 일반적인 경우이기 때문에 예시를 생략하고,
Partition Key와 Sort Key를 구성하는 예시를 들면서 DynamoDB의 PK에 대해 더 이해해보도록 합시다.
예시 테이블은 가수, 노래 정보들이 포함된 Music 테이블이라고 가정하고 예시를 들어보겠습니다.
이때 대표적으로 테이블의 Attribute가 '가수'와 '노래 제목'이 존재한다고 해봅시다.
우선 PK를 구성하려고 할 때 Sort Key의 존재 여부를 결정하기 위해 Attribute를 다음과 같은 기준으로 생각해봤습니다.
- 가수와 노래 제목 모두 중복된 데이터가 들어올 수 있다 - 복합키 관점에서 Sort Key 적용 O
- 비즈니스 요구사항에서 Sort Key 설정 시 조회 성능 향상이 되는 부분이 있다 - 정렬 기능 관점에서 Sort Key 적용 O
Music 도메인에서 비즈니스 요구사항을 생각해보면, 다음과 같은 비즈니스 로직이 있을 수 있습니다.
한 가수가 발매한 노래 제목들을 모두 조회하는 로직
이 경우에, Partition Key만 설정했을 경우와 Sort Key를 설정한 경우를 비교해보면 조회 성능 차이가 있을 것입니다.
Partition Key를 가수로 하고 Sort Key로 노래 제목을 한다면 가수 이름으로 파티션을 조회했을 때
이미 저장될 시점에 노래 제목으로 정렬되어 있기 때문에 조회 성능이 훨씬 좋을 것입니다.
따라서 이러한 경우에 Partition Key + Sort Key를 구성하여 복합키를 이루고 조회 성능까지 향상시킬 수 있을 것 같습니다.
4. Secondary Index
DynamoDB의 Secondary Index를 살펴보면 다음과 같습니다.
- '조회 성능을 향상시키는 효과'로 다른 DB와 인덱스를 사용하는 목적은 같다.
- 하지만, 인덱스 생성 시 PK와 마찬가지로 Partition Key와 Sort Key를 구성해야 한다는 점이 다르다.
일반적인 DB Secondary Index는 column 1개에 생성하지만,
DynamoDB의 Secondary Index는 PK와 마찬가지로 Partition Key와 Sort Key를 지정하여 생성합니다.
DynamoDB의 Secondary Index는 다음과 같은 2가지 종류로 나뉩니다.
- GSI (Global Secondary Index)
- LSI (Local Secondary Index)
해당 2가지 종류의 Secondary Index 특성을 요약해보겠습니다.
4-1. GSI (Global Secondary Index)
GSI의 특성을 요약해보면 다음과 같습니다.
- GSI는 Index의 Partition Key와 Sort Key를 테이블 PK에 설정한 Partition Key, Sort Key와 상관없이 다르게 설정할 수 있다.
- Partition Key는 필수이고, Sort Key는 선택이다.
- 'Global'의 의미는 해당 Index가 테이블 내의 모든 데이터에 적용될 수 있다는 의미이다.
- GSI 생성은 테이블 생성 시 동시에 할 수도 있고, 기존 테이블에 GSI를 추가할 수도 있다.
- 테이블 데이터의 파티션과 별개로 자체 Index 파티션 공간에 저장된다.
- 테이블당 최대 20개의 GSI를 생성할 수 있다.
공식문서에 나온 예제로 예를 들어보겠습니다.
위와 같은 GameScores 테이블의 PK는 다음과 같습니다.
- Partition Key : 'UserId'
- Sort Key : 'GameTitle'
이와 같은 상황에서 다음과 같은 요구사항이 존재할 수 있습니다.
- 게임 제목 별로 제일 높은 점수를 반환할 수 있다.
이 상황에서는 기존 PK의 구조로 검색하게 되면 'UserId'별로 데이터가 파티션에 적재되어 있기 때문에
불필요하게 파티션을 Scan하여 모든 정보를 모으고 해당 정보 내에서 요구사항을 처리해야 합니다.
이때 Partition Key가 'GameTitle'이고 Sort Key가 'TopScore'라면 게임 제목별로 데이터가 파티션에 적재되어 있기 때문에
요청한 게임 제목의 제일 높은 점수를 효율적으로 1개의 파티션을 탐색하여 가져올 수 있습니다.
이렇게 테이블의 Partition Key, Sort Key와 상관없이
새로운 Partition Key, Sort Key로 GSI를 구성하여 효율적인 조회를 할 수 있습니다.
4-2. LSI (Local Secondary Index)
LSI의 특성을 요약해보면 다음과 같습니다.
- LSI는 Index의 Partition Key를 테이블에 설정한 Partition Key와 동일하게 설정해야 하고, Sort Key를 다르게 설정한다.
- Patition Key와 Sort Key가 모두 필수이다.
- 'Local'의 의미는 LSI의 모든 Partition이 테이블의 Partition과 동일하다는 의미이다.
- LSI를 구성할 때 테이블에 설정한 Partition Key와 동일하게 설정해야 하기 때문에 Partition이 동일하다.
- 따라서, 기존 테이블에서 Partition Key는 동일하게 하고 Sort Key만 다르게 하고 싶을 때 사용하는 것이 LSI이다.
- LSI 생성은 테이블 생성 시에만 할 수 있고, 기존 테이블에는 LSI를 추가할 수도 없고 삭제할 수도 없다.
- LSI는 기존 테이블의 파티션에 저장된다.
- 테이블당 최대 5개의 LSI를 생성할 수 있다.
공식문서에 나온 예제로 예를 들어보겠습니다.
위와 같은 Thread 테이블(포럼의 스레드 관련 테이블)의 PK는 다음과 같습니다.
- Partition Key : ForumName
- Sort Key : Subject
이와 같은 상황에서 다음과 같은 요구사항이 존재할 수 있습니다.
- 포럼별로 가장 최신 스레드의 발행 시간을 반환할 수 있다.
이 상황에서는 Partition Key가 ForunName으로 포럼별로 Partition에 적재되어 있기 때문에
그대로 가져와서 'LastPostDateTime'을 기준으로 정렬을 수행하면 해당 요구사항을 구현할 수 있습니다.
하지만, 조금 더 조회 성능을 올리기 위해서는 파티션 내 정렬 조건에 'LastPostDateTime' Attribute가 포함되면 좋을 것입니다.
이때, LSI을 생성하여 Partition Key를 ForumName과 동일하게 설정하고 Sort Key만 LastPostDateTime로 설정하면
해당 조회 성능 향상을 기대할 수 있습니다.
그러나 LSI는 테이블 설계 시에 생성을 해야하고, 테이블당 최대 5개 제한이기 때문에 설계 시 신중하게 생성하는 것이 좋습니다.
'DB' 카테고리의 다른 글
[PostgreSQL] 1. PostgreSQL 내부 구조 알아보기 (feat. 쿼리 처리 과정) (0) | 2024.10.19 |
---|---|
[DB] DB PK 생성 전략 알아보기 (feat. Auto Increment, UUID, ULID, Snowflake ID, TSID) (4) | 2024.09.22 |
[DB] MySQL 및 InnoDB의 DB Lock 알아보기 (1) | 2023.11.19 |
[DB] MySQL InnoDB의 인덱스(feat. 클러스터링 인덱스, 세컨더리 인덱스, 인덱스 스캔 종류, 다중 컬럼 인덱스) (1) | 2023.11.13 |
[DB] DB 인덱스(Index)란? (1) | 2023.11.12 |