중급6분 분량

변경되는 속성에 따라 DynamoDB 정렬

속성을 중심으로 정렬 키를 모델링하여 항목을 순서대로 쿼리할 수 있습니다. 속성이 변경됩니다. 티켓 상태, 주문 상태, 작업 우선순위. DynamoDB의 규칙: 키 속성은 그 자리에서 업데이트할 수 없습니다. 기본 키는 변경할 수 없습니다. 아이템의 수명. 키의 일부인 값을 변경하고 편집하지 않는 경우 항목 — DynamoDB에서 명시적으로 수행하도록 하는 항목 이동입니다.

DynamoDB 정렬 키를 변경할 수 있나요?

아니요. 정렬 키는 기본 키의 일부이며 DynamoDB 키 속성은 변경할 수 없습니다. — UpdateItem는 파티션이나 정렬 키 값을 편집할 수 없으며 "항목 이동" 작업이 없습니다. 이를 변경하려면 이전 항목을 삭제하고 새 항목을 추가하거나 대신 GSI 정렬 키에 휘발성 값을 유지하십시오.

  • 키 속성은 변경할 수 없습니다. 파티션이나 정렬 키는 변경할 수 없습니다. value — DynamoDB에는 "항목 이동" 작업이 없습니다.
  • 키 값을 변경하려면 이전 항목을 삭제하고 새 항목을 입력합니다 — 이상적으로는 transaction 그래서 그것은 원자적입니다.
  • 더 나은 점: 기본 테이블 키에서 휘발성 값을 유지하고 키에 넣습니다. GSI 정렬 키 대신 — GSI 키는 업데이트하기 때문에 변경될 수 있습니다 기본 항목은 인덱스 항목을 다시 전파합니다.
  • 액세스할 때마다 변경되지 않는 정렬 키(타임스탬프, 불변 ID)를 선택하세요. 패턴이 허용됩니다.

문제: 정렬하려는 상태가 계속 변합니다.

지원 데스크를 운영하고 팀의 티켓을 상태별로 정렬하고 싶다고 가정해 보겠습니다. 정렬 키에 상태를 입력합니다.

PK: TEAM#7   SK: STATUS#open#TICKET#8842

이제 티켓이 pending로 이동합니다. 정렬 키만 UpdateItem 하고 싶습니다. STATUS#pending#TICKET#8842 — 그러나 DynamoDB 키를 변경하는 모든 쓰기를 거부합니다. 속성. 키는 항목의 주소입니다. 주소는 내부에서 편집할 수 없습니다. 는 당신이 정렬 기준으로 선택한 상태는 가만히 있지 않을 것입니다.

옵션 1: 삭제하고 다시 생성(원자적으로)

값이 기본 테이블 키에 있어야 하는 경우 값을 변경하면 이전 항목이 제거됩니다. 그리고 새로운 것을 작성합니다:

1. DeleteItem  PK=TEAM#7  SK=STATUS#open#TICKET#8842
2. PutItem     PK=TEAM#7  SK=STATUS#pending#TICKET#8842  (same attributes)

0 내부에서 수행하여 삭제하고 put은 둘 다 성공하거나 둘 다 실패합니다. 그렇지 않으면 둘 사이의 충돌로 인해 해당 값을 잃게 됩니다. 티켓을 복사하거나 복사하세요. 이것은 작동하지만 이제 모든 상태 변경은 두 번의 쓰기와 한 번의 쓰기로 이루어집니다. 거래; 가끔 변경하는 경우에는 괜찮지만 뜨거운 경우에는 비용이 많이 듭니다.

옵션 2: 기본 키에서 변경 가능한 값을 유지합니다(선호).

깔끔한 디자인: 기본 테이블 키를 불변(티켓 ID)으로 만들고 GSI 정렬 키에 휘발성, 정렬 가능한 값을 넣습니다.

Base:  PK: TICKET#8842   status: "open"   teamId: TEAM#7
GSI:   GSI1PK: TEAM#7    GSI1SK: STATUS#open#TICKET#8842

이제 상태 변경은 기본 항목의 status 속성에 대한 일반 UpdateItem입니다. status는 기본 테이블 키가 아니기 때문에 DynamoDB가 _허용_합니다. 그러면 DynamoDB GSI 항목을 자동으로 새로운 정렬 위치로 다시 전파합니다. 하나의 API 호출, 원자성이 자동으로 처리됨 — 트랜잭션 없음, 삭제 댄스 없음(DynamoDB 내부) 여전히 이전 인덱스 항목을 삭제하고 새 항목을 작성하므로 인덱스 변경 비용은 ~3입니다. 트랜잭션 삭제 및 넣기의 ~4에 대해 단위를 작성합니다.

아니요, GSI 정렬상태가 open에서 pending으로바뀜값이 베이스 테이블 키인가?트랜잭션에서 삭제 재생성일반 UpdateItem; GSI가 재전파

절충: GSI는 eventually consistent 추가 저장/쓰기 비용이 들지만 값이 자주 변경되는 경우에는 다소 부담스럽습니다. 모든 변경 시 삭제하고 다시 만드는 것보다 저렴하고(~3 대 4 쓰기 단위) 훨씬 간단합니다.

DynoTable에서 키 디자인하기

기본 읽기와 GSI 읽기 모두에 대한 주요 조건을 구축하고 미리 봅니다. DynamoDB expression builder.

DynoTable에서는 쿼리가 실행되는 인덱스를 선택하고 휘발성을 관찰합니다. 기본 항목이 불변 키를 유지하는 동안 GSI에서 값 정렬 — 둘 다 나란히 읽습니다. 실제 데이터 측면.

DynoTable에서 베이스 항목은 불변 키를 유지한 채, 상태로 정렬된 GSI를 쿼리하는 모습.
DynoTable에서 베이스 항목은 불변 키를 유지한 채, 상태로 정렬된 GSI를 쿼리하는 모습.

함정과 다음 단계

  • 키 속성을 UpdateItem으로 바꾸려 하지 마세요. 거절됩니다. 키 값은 항목 수명 동안 고정입니다.

  • 꼭 옮겨야 한다면 삭제+put을 트랜잭션으로 — 보호 없는 두 번의 쓰기로 하지 마세요.

  • 불변 베이스 키 + GSI를 우선하세요. 정렬에 쓰고 그리고 변하는 모든 속성에 대해.

  • GSI 최종적 일관성을 잊지 마세요 — 다시 정렬된 항목은 짧은 전파 지연 뒤에 나타납니다.

  • 관련: 정렬 키 전략, GSI vs LSI, 트랜잭션.

가변 속성이 GSI에서 베이스 테이블과 비교해 어떻게 정렬되는지 보고 싶나요? DynoTable 다운로드하고 인덱스를 직접 탐색하세요.

쓰기 비용: 삭제 후 put vs GSI 업데이트

us-east-1 온디맨드에서 1 KB 티켓 항목의 대략 WCU 비교입니다(실제 과금은 AWS 반올림 규칙을 따릅니다).

패턴API 호출전형적인 WCU 영향
베이스 키에서 트랜잭션 삭제 + putTransactWriteItems (2 ops)트랜잭션 요금으로 ops당 항목 크기의 약 2×
status 속성 업데이트, GSI 재전파UpdateItem 1회베이스 쓰기 + GSI 쓰기(1 KB 항목 + 프로젝션 속성에서 약 2 WCU)

GSI 경로는 앱 수준 오케스트레이션을 피하고, 삭제와 put 사이 충돌로 행이 사라지는 창을 없앱니다. 더 단순한 쓰기 대신 인덱스 읽기의 최종적 일관성을 받아들입니다.

분당 상태 변경이 많다면 요금 계산기로 항목 크기와 업데이트 비율을 모델링하세요.

상태 정렬 목록용 희소 GSI

open 티켓만 상태 정렬 큐가 필요하면 희소 인덱스를 쓰세요. status = open인 동안만 GSI1PK = TEAM#7, GSI1SK = STATUS#open#...를 씁니다. 티켓이 닫히면 업데이트에서 GSI 키 속성을 제거하거나 생략합니다 — 베이스 정렬 키에서 삭제+put 없이 인덱스에서 빠집니다.

인덱스를 작게 유지하고 목록하지 않는 닫힌 티켓을 인덱싱하지 않습니다.

선호할 불변 베이스 키

변동 필드베이스 테이블 SK더 나은 베이스 SK변동 필드 위치
주문 상태STATUS#shipped#ORD#99ORD#99GSI 정렬 또는 속성
작업 우선순위P#1#TASK#12TASK#12GSI 정렬
사용자 표시 이름NAME#alice#USER#5USER#5비키 속성

타임스탬프와 불변 id(CREATED#2026-06-27T10:00:00Z, TICKET#8842)는 베이스 테이블 자체에서 시간순이 필요할 때 안정적인 베이스 정렬 키가 됩니다.

코딩 전에 GSI 설계

싱글 테이블 설계 도구에서 액세스 패턴을 매핑하세요 — "팀별·우선순위순으로 미해결 티켓 목록"을 넣고 제안된 GSI1PK / GSI1SK 템플릿을 확인합니다. 그다음 식 빌더로 키 조건을 만들고 쿼리 빌더로 페이지 쿼리를 내보내 통합 테스트에 쓰세요.

상태 변경 후 read-your-writes

UpdateItem베이스 테이블에 대한 강력하게 일관된 읽기는 새 status를 즉시 보여 줍니다. GSI 쿼리는 잠시 늦을 수 있습니다. GSI 정렬 큐로 리다이렉트하는 UI는 오래된 행을 허용하거나, 정밀도가 필요하면 id로 베이스에서 다시 가져오세요.

업데이트됨