DynamoDB GSI가 내부적으로 저장되는 방법
은 테이블에 대한 포인터가 아닙니다. 별도입니다. 내부적으로 관리되는 테이블 — 자체 파티션, 자체 키 스키마, 자체 용량 — DynamoDB가 쓰기를 비동기식으로 복사하여 동기화를 유지합니다.
SQL에서 나오는 인덱스는 동일한 물리적 테이블에 연결되어 업데이트된 B-트리입니다. 동일한 거래 내에서. GSI는 이러한 가정을 모두 깨뜨리고 거의 모든 GSI의 놀라움은 바로 그 한 가지 사실로 거슬러 올라갑니다.
DynamoDB GSI는 어떻게 저장되나요?
DynamoDB GSI는 기본 테이블에 대한 포인터가 아닌 별도의 내부 관리 테이블(자체 파티션, 키 스키마 및 용량)로 저장됩니다. DynamoDB는 각 쓰기를 인덱스에 비동기식으로 복사하여 GSI 키, 기본 테이블 키 및 모든 속성만 저장합니다.
- GSI는 자체 테이블입니다. 기본 테이블이 아닌 GSI의 파티션 키입니다.
- 쓰기는 비동기식으로 복제됩니다. 쓰기는 먼저 기본 테이블에 커밋됩니다. 그런 다음 DynamoDB는 이를 백그라운드 경로의 각 GSI로 팬아웃합니다.
- 프로젝션된 속성만 저장됩니다. 인덱스는 GSI 키, 기본 키를 보유합니다. 키와 예상한 모든 속성 외에는 아무것도 없습니다.
- GSI 키는 고유할 필요가 없습니다. 여러 기본 항목이 하나의 GSI를 공유할 수 있습니다. 파티션/정렬 키; 베이스 는 그들을 유지하는 타이브레이커입니다. 뚜렷하다.
하나의 기본 항목으로 시작
SaaS 감사 로그를 작성하세요. 작업 공간에서 모든 권한 있는 작업은
불변의 사건. 기본 테이블 WorkspaceEvents에는 키가 지정되어 있으므로 모든
작업 공간의 이벤트는 시간순으로 하나의 로 진행됩니다.
| EventPK | EventSK | actorId | verb | targetRef |
|---|---|---|---|---|
| WS#orbit-9 | TS#2026-06-23T14:02:11Z | USR#kp | ROLE_GRANTED | USR#mara |
작업 공간별 EventPK = "WS#orbit-9" 파티션; EventSK은 ISO 타임스탬프이므로
a Query는 한 작업 공간의 이벤트를 시간순으로 반환합니다. 그것은 봉사한다
"이 작업공간의 타임라인을 보여주세요"가 완벽합니다.
그것은 다른 어떤 것도 제공하지 않습니다. "USR#kp이 매 시즌마다 무엇을 했는지 물어볼 수는 없습니다.
작업실?" — actorId는 열쇠가 아니므로 기본적으로 대답할 수 있는 유일한 방법입니다.
테이블이 5 가득 찼습니다. 이것이 GSI의 액세스 패턴입니다.
추가하기 위해 존재합니다.
GSI를 추가하고 두 번째 테이블이 나타나는지 확인하세요.
동일한 이벤트를 수행한 사람에 따라 다시 분할하는 GSI ByActor를 정의합니다.
ByActor (GSI)
partition key = actorId ("USR#kp")
sort key = EventSK ("TS#2026-06-23T14:02:11Z")
DynamoDB는 이제 두 번째 물리적 구조를 유지합니다. 동일한 논리적 사건은
두 번 저장 — 기본 테이블의 WS#orbit-9 파티션에 한 번, 그리고 다시
GSI의 USR#kp 파티션:
| actorId | EventSK | EventPK | verb |
|---|---|---|---|
| USR#kp | TS#2026-06-23T14:02:11Z | WS#orbit-9 | ROLE_GRANTED |
무엇을 탔는지 확인하세요. 기본 테이블의 키(EventPK, EventSK)가 저장됩니다.
모든 GSI 항목에 자동으로 포함됩니다. 이것이 바로 GSI 히트가 사용자를 다시
전체 항목 — 그리고 왜 2
인덱스에는 여전히 저장 공간이 필요합니다.
GSI에는 실제로 무엇이 살고 있나요?
색인은 전체 항목을 복사하지 않습니다. 각 GSI 항목에는 정확히 3개의 항목이 포함됩니다. 당신은 세 번째 것만 제어할 수 있습니다.
| GSI에 저장됨 | 어디에서 오는가 | 선택 과목? |
|---|---|---|
| GSI 파티션 + 정렬 키 | GSI 키로 명명한 속성 | 아니요 |
| 기본 테이블 키 | 모든 기본 항목에서 복사됨 | 아니요 |
| 예상 속성 | 귀하의 Projection 선택 | 예 |
Projection는 KEYS_ONLY, INCLUDE(명명된 목록) 또는 ALL입니다. 에 Query
GSI는 색인에 있는 속성만 반환할 수 있습니다.
예상되지 않은 항목을 요청하면 DynamoDB가 해당 항목을 투명하게 가져오지 않습니다 — 해당 필드에 대해서는 아무것도 돌려받지 못합니다. (AWS GSI docs)
이것이 반전된 관계형 트랩입니다. SQL은 다음을 위해 힙에 다시 조인합니다. 열이 누락되었습니다. GSI는 절대 그렇지 않습니다. 은 전체 계약입니다.
쓰기가 인덱스에 도달하는 방법
복제는 SQL 직관을 가장 어렵게 만드는 부분입니다. 기본 쓰기 및 인덱스 업데이트는 하나의 원자적 작업이 아닙니다.
99하면 DynamoDB는 기본 테이블에 지속적으로 커밋하고 작성하고 그런 다음 각 항목을 업데이트하는 백그라운드 경로에 변경 사항을 전파합니다. GSI. 승인은 인덱스를 기다리지 않습니다.
감사 쓰기 이벤트 순서(위에서 아래로):
발신자는 4~6단계가 끝나기 전에 3단계에서 200 OK를 얻습니다.
따라서 공백에 있는 ByActor의 Query은 새로운 이벤트를 놓칠 수 있습니다.
이러한 비동기성은 결함이 아니라 의도된 것입니다. 이는 2007년의 계보입니다. Amazon Dynamo paper, 동기식 일관성보다 가용성을 선택한 것입니다. 전체 결과가 살아있습니다 why a GSI is eventually consistent에.
GSI 키는 고유 키가 아닙니다.
SQL에서는 고유하지 않은 보조 인덱스가 기본값이고 고유한 보조 인덱스는 당신이 선택하는 제약. GSI는 그 반대입니다. 고유성이 없음 보장합니다.
충돌하는 타임스탬프에서 동일한 액터의 두 감사 이벤트는
GSI1PK 그리고 GSI1SK도 마찬가지입니다. DynamoDB는 두 가지를 모두 저장하므로 두 가지를 명확하게 구분합니다.
내부적으로 항상 전달되는 기본 테이블의 기본 키에 의해 수행됩니다.
따라서 한 순간에 한 배우에 대한 GSI Query는 여러 개를 합법적으로 반환할 수 있습니다.
항목. SQL 고유 인덱스가 제공하는 방식으로 키당 하나의 행을 가정한 경우,
그게 바로 풋건이에요.
인덱스를 쿼리하면
DynamoDB Expression Builder는 다음을 쓴다.
이름과 값이 올바르게 이스케이프된 KeyConditionExpression — 예: 매칭
컷오프 이후 한 명의 배우:
KeyConditionExpression: "#a = :actor AND #ts > :since"
ExpressionAttributeNames: { "#a": "actorId", "#ts": "EventSK" }
ExpressionAttributeValues: {
":actor": { "S": "USR#kp" },
":since": { "S": "TS#2026-06-01T00:00:00Z" }
}용량은 테이블이 아닌 인덱스에 따라 결정됩니다.
GSI는 자체 테이블이므로 자체 읽기 및 쓰기 용량을 갖습니다.
기본 테이블과 별도로 요금이 청구되고 제한됩니다. ByActor를 읽으면 소비됩니다.
GSI의 읽기 단위이며 테이블의 읽기 단위는 아닙니다.
역방향 결합은 문제가 되는 것입니다. 모든 기본 테이블 쓰기는 또한 GSI가 이를 흡수할 수 없으면 기본 쓰기에 역압을 가합니다. 그 메커니즘은 자체 가이드를 얻습니다 — when a GSI throttles base-table writes.
이는 GSI의 파티션 키가 기본 테이블만큼 중요한 이유이기도 합니다. 에이 카디널리티가 낮은 GSI 키는 기본 파티션인 경우에도 하나의 인덱스 파티션에 쓰기를 뭉칩니다. 쓰기는 완벽하게 분산됩니다. 즉, 키를 다시 입력하여 생성한 핫 파티션입니다.
GSI 쓰기 증폭(청구)
GSI에 프로젝션하는 모든 베이스 테이블 쓰기는 us-east-1 온디맨드에서 베이스 WCU + 인덱스 WCU가 듭니다. ALL 프로젝션의 1 KB 항목은 보통 합계 약 2 WCU — 테이블 행 1, 인덱스 복사 1 — 를 청구합니다. KEYS_ONLY는 인덱스 쓰기를 줄이고, ALL은 스토리지와 쓰기 증폭을 두 배로 만듭니다. 항목 크기와 프로젝션은 요금 계산기로 모델링하세요.
함정과 다음 단계
- 예상되지 않은 속성이 다시 나타날 것이라고 기대하지 마십시오. GSI
Query는 다음과 같은 속성만 반환합니다. 인덱스 저장소. 전체 항목이 필요한 경우 프로젝션하거나 다음에서 가져옵니다. 휴대된 키에 의한 기본 테이블입니다. - GSI 키를 고유한 키로 취급하지 마세요. 둘 이상의 키를 반환하려면
Query을 계획하세요. 키당 항목; 기본 기본 키는 유일한 실제 ID입니다. - GSI를 제공한 쓰기 직후에는 GSI를 읽지 마세요. 비동기 경로는 인덱스에는 아직 쓰기가 표시되지 않을 수 있습니다. 필요할 때 기본 테이블을 읽으십시오. 자신이 쓴 글을 읽습니다.
- GSI의 용량 크기를 의도적으로 조정합니다. 읽기 및 읽기와 독립적입니다. 쓰기에 대한 숨겨진 종속성.
전체 게임은 패턴을 제공하는 주요 모양을 선택하는 것입니다. single-table design는 여러 GSI에 걸쳐 하나의 GSI를 과부하합니다. 그들 중; GSI vs LSI은 로컬 인덱스가 대신 맞는 경우를 다룹니다.
다음에서 GSI KeyConditionExpression을 구축하고 미리 보세요.
DynamoDB Expression Builder, 그럼
try DynoTable 인덱스의 예상 속성을 검사하고 관찰합니다.
자신의 테이블에 있는 GSI에 복제를 기록합니다.