중급6분 분량

DynamoDB 파티션 키의 작동 방식

여러분의 파티션 키는 컬럼이 아닙니다 — 주소입니다. DynamoDB가 그 키를 해싱하고, 그 해시가 어느 물리 머신이 아이템을 저장할지 결정합니다. 키를 잘 고르면 부하가 퍼지고, 잘못 고르면 한 서버가 열을 다 받습니다.

DynamoDB 파티션 키는 어떻게 작동하나요?

DynamoDB는 파티션 키를 내부 해시 함수에 통과시키고, 그 해시가 어느 물리 파티션이 아이템을 저장할지 결정합니다. 키는 SQL 컬럼처럼 정렬되거나 인덱싱되지 않습니다 — 주소입니다. 고카디널리티 키를 고르면 부하가 여러 파티션에 퍼지고, 저카디널리티 키를 고르면 단일 파티션이 모든 부하를 떠안습니다.

  • 키는 정렬되는 게 아니라 해싱됩니다. DynamoDB는 파티션을 고르기 위해 여러분의 파티션 키를 내부 해시에 통과시킵니다. 인접한 두 값은 디스크에서 서로 전혀 가깝지 않은 곳에 떨어집니다.
  • 파티션은 실제 저장 단위입니다. 각각은 약 10 GB, 초당 3,000 읽기 단위, 초당 1,000 쓰기 단위에서 한계에 다다릅니다. 여러분의 트래픽은 키가 퍼지는 파티션 수로 나뉩니다.
  • 핫 키가 지뢰입니다. 대부분의 요청을 한 파티션 키 값으로 깔때기처럼 몰면 그 파티션에서 스로틀이 걸리고 나머지 테이블은 놀고 있습니다.
  • 고카디널리티 키가 이깁니다. 서로 다르고 고르게 맞는 키 값이 많을수록, 더 많은 파티션이 부하를 흡수합니다.

키가 실제로 하는 일에서 시작하기

SQL에서 왔다면 기본 키는 JOIN하고 ORDER BY 하는, 정렬되고 인덱싱된 컬럼입니다. DynamoDB의 파티션 키(때로 해시 키라고도 함)는 다른 일을 합니다. 배치 를 결정합니다.

DynamoDB는 파티션 키를 내부 해시 함수에 넣습니다. 출력은 키스페이스에 매핑되고, 키스페이스는 범위로 쪼개집니다 — 각 범위는 하나의 물리 파티션이 소유합니다. 그 파티션은 실제 노드 위의 실제 저장 공간입니다.

그래서 파티션 키는 한 가지 질문에 답합니다. 어느 머신이 이 아이템을 담는가? 정렬 키는, 있다면, 그 머신 안에서 아이템을 정렬할 뿐입니다. 배치에는 아무 역할도 하지 않습니다.

해시를 통해 쓰기 하나 따라가기

장치 측정값을 수집하는 SaaS를 운영한다고 합시다. 테이블 SensorReadings는 파티션 키 deviceId와 정렬 키 readingTs를 사용합니다. deviceId = "vac-7741"에 대한 측정값을 씁니다.

그 쓰기가 거치는 경로는 다음과 같습니다 — 여러분의 키에서 그것이 안착하는 디스크까지:

키스페이스 조각PutItemdeviceId = 'vac-7741'파티션해싱해시가 키스페이스의 지점에 매핑됨어느 범위가소유하는가?파티션 P2아이템 저장,readingTs로 정렬됨

vac-7741에 대한 쓰기는 키스페이스의 한 지점으로 해싱되고, 그 지점은 P2의 범위에 떨어지며, 아이템은 P2에 안착합니다 — 거기서 readingTs로 정렬됩니다.

체화해야 할 점: "vac-7741""vac-7742"는 한 글자 차이지만, 그 해시는 서로 무관합니다. 둘은 거의 확실히 서로 다른 파티션에 삽니다. 파티션 키스페이스에는 "가까운 것"이 없습니다.

이것은 DynamoDB가 원래 설계에서 물려받은 일관된 해싱 아이디어입니다 — 2007년 Amazon Dynamo 논문("Dynamo: Amazon's Highly Available Key-value Store")은 어떤 단일 노드도 병목이 되지 않도록 정확히 해싱으로 키를 노드에 퍼뜨렸습니다.

파티션의 단단한 한계를 존중하세요

물리 파티션은 유한합니다. AWS DynamoDB 개발자 안내서에 따르면, 각각은 대략 다음까지 담습니다:

한계파티션당
저장 용량~10 GB
읽기 처리량초당 3,000 읽기 단위
쓰기 처리량초당 1,000 쓰기 단위

파티션이 10 GB를 넘겨 차거나 프로비저닝된 처리량이 더 많은 여유를 필요로 하면, DynamoDB는 그것을 분할합니다 — 키스페이스 범위가 나뉘고 아이템이 더 많은 파티션에 재분배됩니다. 이는 자동이며, 여러분이 유발하지 않습니다.

함정: 분할은 아이템을 그 해시 로 퍼뜨립니다. 모든 핫 요청이 단일 파티션 키 값을 겨냥하면, 분할은 도움이 안 됩니다 — 그 모든 트래픽이 여전히 같은 지점으로 해싱됩니다. 단일 키의 부하는 파티션에 걸쳐 분할할 수 없습니다.

함정에 이름을 붙이기: 핫 파티션

핫 파티션은 고전적인 지뢰입니다. 하나의 파티션 키 값(또는 아주 작은 집합)이 트래픽의 불균형한 몫을 흡수할 때 발생합니다.

구체적 실패: SensorReadings"us-east", "eu-west" 같은 값을 가진 파티션 키 region으로 바꿉니다. 세 리전은 세 키 값을 뜻하고 — 기껏해야 — 실제 일을 하는 파티션 셋을 뜻합니다. "us-east"를 읽기로 두드리면 그것은 3,000 RCU에서 스로틀되는 반면 테이블의 총 프로비저닝 용량은 쓰이지 않은 채 놓여 있습니다.

DynamoDB의 적응형 용량은 이를 완화합니다 — 쓰이지 않은 처리량을 바쁜 파티션 쪽으로 옮길 수 있고, 단일 초고온 키를 자기만의 파티션으로 격리할 수 있습니다. AWS는 re:Invent "Advanced Design Patterns for DynamoDB" 심층 세션에서 이를 상세히 다뤘습니다. 하지만 적응형 용량은 시간을 벌어 줄 뿐 면역을 주지 않습니다 — 개별 키 하나의 부하를 세분할 수는 없습니다. 분산을 위해 설계하세요. 안전망에 기대지 마세요.

고카디널리티 키를 고르세요

해법은 카디널리티 — 서로 다른 키 값의 수, 그리고 트래픽이 그것들에 얼마나 고르게 맞는지 — 입니다.

  • 저카디널리티(region, status, true/false): 파티션이 적고, 트래픽이 집중되며, 일찍 스로틀됩니다.
  • 고카디널리티(deviceId, userId, 주문 ID): 많은 값이 많은 파티션에 걸쳐 해싱되고, 부하가 퍼지며, 여유가 늘어납니다.

SQL에서는 기꺼이 status 컬럼을 인덱싱하고 그것으로 필터링했을 겁니다. DynamoDB 파티션 키로서 그것은 함정입니다 — 퍼질 수 없습니다. 저카디널리티 속성은 필터로, 또는 보조 인덱스의 정렬 키로 두되, 배치를 결정하는 것으로는 절대 두지 마세요.

자연적으로 좋은 키가 그래도 치우칠 때 — 나머지를 압도하는 소수의 고래 테넌트 — 하나의 논리적 값을 N개의 파티션에 부채꼴로 펼치도록 접미사를 추가하세요. 예: 샤딩된 쓰기 경로를 위한 tenantId#3. 읽을 때 다시 집계합니다.

키가 퍼진 뒤 파티션 안에서 아이템을 겨냥하려면, 정렬 키에 대한 KeyConditionExpression을 씁니다. 코드에 연결하기 전에 여러분 자신의 스키마에 대해 하나를 DynamoDB 표현식 빌더에서 조립할 수 있습니다:

deviceId = "vac-7741" AND readingTs BETWEEN "2026-06-01" AND "2026-06-30"

그것은 한 장치의 6월 구간을 단일 파티션에서 읽습니다 — Scan이 아니라 Query입니다. 파티션 키가 머신을 고정하고, 정렬 키 조건이 행을 좁힙니다.

함정과 다음 단계

  • SQL에서 잘 읽히는 것으로 키를 고르지 마세요. 퍼지는 것으로 고르세요. 카디널리티가 먼저, 쿼리 편의는 둘째입니다.
  • 테이블의 총 용량이 키당 여러분 것이라고 가정하지 마세요. 처리량은 파티션별입니다. 하나의 핫 값이 스로틀되는 동안 테이블은 놀고 있는 것처럼 보일 수 있습니다.
  • 분할과 싸우지 마세요. 그것은 자동이고 해시 기반입니다 — 여러분의 일은 그것이 퍼질 수 있도록 충분히 많은 서로 다른 키를 주는 것입니다.

키가 깔끔하게 퍼지고 나면, 다음 결정은 파티션 안에서 아이템을 어떻게 배치할지입니다 — 단일 테이블 설계를 보세요 — 그리고 두 번째 액세스 패턴에 보조 인덱스가 옳은 도구일 때입니다.

DynoTable을 다운로드해 여러분의 실제 파티션과 키 분포를 둘러보고, 핫 키가 여러분을 호출하기 전에 짚어 내세요.

업데이트됨