본문 바로가기

IT/NOSQL

[DynamoDB] Partition Key 설계 원칙 및 고려사항

1. DynamoDB Partitioning 원리

  • DynamoDB는 자체 내부 Hash Function이 있다.
  • Partition Key값을 파라미터로 계산된 Hash Value를 기준으로 DynamoDB Table 내부의 파티션이 결정되어 데이터는 적재된다.
  • Primary Key가 복합키인 경우에도 단일 Partition Key로 이루어진 경우와 같은 방식으로 partition key hash값을 계산하여 partition에 적재한다.
  • 그러나 같은 partition key를 가진 데이터들은 물리적으로 가깝게 설계되며, Sort Key 값으로 정렬된다.

 

 

 

 

2. Partition Key 설계시 고려사항

 

2-1. 분산된 워크로드

  • Partition Key는 테이블에서 데이터가 저장되는 논리적 및 물리적 파티션을 결정하는 요소이다.
  • DynamoDB는 결정된 파티션들에게 프로비저닝된 Capacity Unit을 균일하게 분배한다.
  • 즉, Partition Key의 분산도를 고려하지 않고 설계시, 요청에 대해 효율적인 Capacity Unit을 사용할 수 없게 된다.
  • 물론 DynamoDB는 관리형 서비스이기 때문에 어느정도 조절은 해 주지만, 최적화를 위해서는 위 관리형 서비스에 의존하지 않고, 직접 튜닝하는 것이 적절하다.

 

 

 

다음 데이터는 실제로 필자가 DynamoDB를 학습하며 설계하였던 테이블이다. (나중에 이 테이블을 보니 최악이었다 :(  ) 

 

 

위 테이블의 경우, 사내 회의실 예약 시스템에 대한 정보를 구현하기 위해 설계한 내역이며, partition key가 INFO_TYPE이며, sort key가 HASH_VALUE로 설계되었다. 

현재 위 테이블의 Partition Key의 값은 단 2개로 나뉘어져 있다. 위 DynamoDB Partition 아키텍처는 다음과 같이 그림으로 나타낼 수 있다.

 

 

 

 

 

위 아키텍처를 염두에 두고 생각해보자. 회의실의 개수는 건물에 한정적이고, 이 한정적인 회의실에서는 수많은 직원들이 회의실을 사용한다.

그러므로 상대적으로 회의실 정보보다 예약 정보가 훨씬 많을 것이고, 데이터에 대한 접근도 예약정보가 훨씬 많을 것이다.

그 결과, 같은 Capacity Unit을 제공받은 partition이지만, I/O요청이 압도적으로 많은 "res" partition key를 가진 파티션은 그만큼 비효율적인 요청처리를 하게 된다.

 

 

 

 

다음 아키텍처는 위 아키텍처를 조금이나마 개선한 아키텍처이다. (극단적인 예시이므로 참고만 해주길 바란다.)

위같이 설계를 바꾼 이유는 다음과 같다.

  • 회의실에 대한 예약은 현재 HASH_VALUE값 자체를 이용하며, [회의날짜]#[회의실]#[회의시작시간]#[회의종료시간] 의 format을 가진다.
  • 시간의 흐름 중에서 뽑은 하나의 시간 표본은 유일하다.
  • HASH_VALUE도 시간 값 이므로, 유일한 값이다.
  • 위 HASH_VALUE를 Partition Key로 설계하면 Partition의 분포도가 좋아진다.
  • 그러므로 한 파티션에 대한 I/O 병목현상이 개선될 수 있다.

 

 

 

 

 

 

2-2. Partition Key에 난수 추가 (Sharding)

  • Sharding은 Partitioning의 한 부분이며, "Horizontal Partitioning"과 같은 의미이다.

  • 기존 설계한 Partition Key에 난수를 추가하게 되면, Hash Function에 의해 결과값이 다양해진다.
  • 그 결과로 DynamoDB 내부의 논리적 및 물리적 파티션의 분포는 분산된다.
  • 파티션이 분산됨에 따라 병렬처리를 개선할 수 있다.

 

2-3. Partition Key를 이용한 효율적인 쓰기 작업 분산

  • DynamoDB는 기본적으로 파티션의 크기와는 상관 없이 균일한 Capacity Unit을 할당받는다.
  • DynamoDB는 관리형 서비스이기 때문에 어느정도 파티션간 Capacity Unit을 프로비저닝 해주지만, 이에 의존한 key설계는 올바르지 못하다.
  • 그러므로, 쓰기 작업에 대해서도 타겟 파티션을 분산시켜 정의할 필요가 있다.

 

 

case1. partition key의 정렬 순서대로 데이터를 쓰는 경우

 

  •  위와 같이 쓰기작업을 정의할 시, 한 파티션의 Capacity Unit을 집중적으로 쓰기 때문에 병목현상이 발생 할 수 있다.

표 출처 : AWS DynamoDB 설명서

 

 

case2. partition key의 순서와 무관하게 분산시켜 데이터를 쓰는 경우

표 출처 : AWS DynamoDB 설명서

  • 위와 같이 쓰기 작업을 개선할 시, 매 작업마다 다른 파티션의 Capacity Unit을 사용하기 때문에 case1 보다 Capacity Unit의 사용률에 대해 보다 유연하게 대처 가능하다.

 

 

 

 

 

3. 참고문헌