고급5분 분량

DynamoDB GSI가 기본 테이블 쓰기를 제한하는 이유

당신은 당신의 테이블에 글을 씁니다. 처리량 예외로 인해 쓰기가 실패하지만 예외 이름은 테이블이 아닌 Global Secondary Index입니다. 테이블에는 여유가 있어요 용량.

SQL에서 보면 말도 안 되는 소리입니다. 보조 인덱스는 INSERT을 차단할 수 없습니다. 에서 DynamoDB는 가능하며 메커니즘을 GSI 배압이라고 합니다.

DynamoDB GSI가 기본 테이블 쓰기를 조절하는 이유는 무엇입니까?

DynamoDB는 모든 쓰기가 각 GSI에도 복제되기 때문에 기본 테이블 쓰기를 조절하고, GSI 파티션이 해당 공유를 흡수할 수 없는 경우 DynamoDB는 역압을 적용하여 인덱스가 영구적으로 뒤처지는 것을 방지합니다. 따라서 프로비저닝이 부족하거나 카디널리티가 낮은 GSI 키는 기본 테이블 쓰기 속도의 엄격한 상한선이 됩니다.

  • 기본 테이블에 쓰면 모든 GSI에도 씁니다. GSI가 흡수할 수 없는 경우 DynamoDB는 기본 테이블 쓰기를 조절하여 인덱스가 영원히 뒤처지게 됩니다. (AWS docs)
  • 짝수 기본 테이블은 도움이 되지 않습니다. GSI는 자체 키로 분할됩니다. 낮은 카디널리티 GSI 키(예: status)는 짝수를 생성합니다. 기본 테이블 쓰기가 완벽하게 분산된 경우.
  • 피해자에 대해서는 예외가 있습니다. GSI의 ResourceArn 포인트; 실제로 제한되는 작업은 테이블에 대한 쓰기입니다.
  • 수정은 재시도 루프가 아니라 용량 또는 주요 설계입니다 — GSI 처리량을 높입니다. 또는 확산되는 GSI 를 선택하세요.

단일 쓰기가 인덱스에 미치는 영향

기본 테이블의 PutItem은 1회 쓰기가 아닙니다. DynamoDB는 항목의 최종적으로 일관된 방식으로 속성을 각 GSI에 비동기적으로 투영했습니다. 모델. 하나의 논리적 쓰기가 N개의 물리적 쓰기(테이블과 모든 인덱스)로 팬아웃됩니다.

복제는 무료도 아니고 선택 사항도 아닙니다. GSI가 계속 따라가야 합니다. 인덱스는 모든 작업에서 테이블에서 더 멀리 표류합니다.

이러한 드리프트를 중지하기 위해 DynamoDB는 역압력을 적용하여 소스를 제한합니다. 인덱스가 무한정 오래되지 않도록 작성하세요.

따라서 GSI의 쓰기 용량은 기본 테이블 쓰기 속도의 엄격한 상한선입니다. GSI에 직접 쓰지 않더라도 말이죠.

실제 사례: 주문 테이블

주문 테이블을 실행한다고 가정해 보겠습니다. 기본 항목:

fieldvaluenote
PK"CUST#8841"partition key
SK"ORD#2026-06-23#A7"sort key
order_state"PROCESSING"
warehouse"EU-MAD-2"
total_cents4990

기본 테이블 쓰기가 정상입니다. CUST#...은 카디널리티가 높으므로 순서 쓰기 기본 파티션 전체에 고르게 분산됩니다. 단축키가 없고 용량이 넉넉합니다.

이제 "주어진 상태의 모든 주문을 보여주세요"에 응답하는 GSI를 추가합니다.

GSI: orders-by-state
fieldvaluenote
GSI-PKorder_state"PENDING" | "PROCESSING" | "SHIPPED" | "CANCELED"
GSI-SKSK

네 가지 가능한 파티션 키 값. 반짝 세일 기간에는 거의 모든 신규 주문이 order_state = "PENDING"에 착륙했습니다. 모든 쓰기는 동일합니다. GSI 파티션.

해당 파티션에는 파티션당 처리량 제한이 있으며 방금 목표한 것은 그것에 전체 쓰기 폭풍이 있습니다.

기본 테이블은 괜찮습니다. PENDING GSI 파티션에 불이 붙었습니다. DynamoDB 인덱스를 보호하기 위해 베이스 테이블 PutItem를 조절합니다.

너를 물어뜯는 흐름

역압 경로 — 기본 쓰기 균형, 인덱스 쓰기 집중:

PutItemorder_state=PENDING베이스 테이블CUST#로 분산GSI로비동기 복제GSI 파티션PENDING (핫)파티션 한도초과베이스 쓰기를스로틀

스로틀이 뒤로 이동합니다. 핫 GSI 파티션이 기본 테이블 쓰기를 거부합니다. 그게 먹였어.

직감이 아닌 예외를 읽어보세요

예외 유형은 어느 한도에 도달했는지 정확하게 알려줍니다. ResourceArn GSI의 이름을 지정합니다. 조절된 작업은 여전히 테이블 쓰기입니다.

모드이유 코드무엇이 다 떨어졌는가
프로비저닝됨IndexWriteProvisionedThroughputExceededGSI의 프로비저닝된 쓰기 용량
둘 다IndexWriteKeyRangeThroughputExceeded단일 핫 GSI 파티션
주문형IndexWriteMaxOnDemandThroughputExceededGSI가 구성한 최대 주문형 한도
주문형IndexWriteAccountLimitExceeded계정/지역 처리량 경계

출처: Understanding GSI write throttling and back pressure.

KeyRange 이유는 위의 핫 파티션 사례에 대한 경품입니다. 전반적으로 하나의 주요 범위가 포화되어도 GSI 용량은 괜찮아 보일 수 있습니다.

어떻게 해결하는가

GSI 공간을 제공하세요. 가장 간단한 원인은 부족한 프로비저닝입니다. GSI에는 테이블과 완전히 분리된 자체 읽기 및 쓰기 용량 — 참조 GSI vs LSI.

테이블을 넉넉하게 프로비저닝하고 GSI를 얇게 남겨둔 경우 GSI의 쓰기 용량(또는 요청 시 최대값).

파티션 키를 수정합니다. 용량은 카디널리티가 낮은 키를 저장하지 않습니다. 단일 핫 파티션을 아웃프로비저닝합니다. 분산되는 GSI 파티션 키를 선택하세요.

구성하십시오: order_state#shard 여기서 shard는 작은 임의의 접미사 또는 접미사입니다. (PENDING#2026-06-23)의 날짜입니다. 쓰기가 여러 파티션에 분산되어 있어도 여전히 Query 샤드를 쿼리하여 상태를 확인합니다.

더 적은 수의 속성을 프로젝트합니다. 각 GSI 쓰기는 예상된 속성을 복사합니다. 에이 KEYS_ONLY 또는 촘촘한 INCLUDE 투영은 인덱스 쓰기가 더 적고 더 적음을 의미합니다. ALL보다 압력이 높습니다. 색인에서 결코 읽지 못할 내용을 예상하지 마십시오.

보고용으로만 사용되는 경우 GSI를 삭제하세요. "주별 주문"이 핫 경로가 아닌 가끔 관리 질문, 필터를 사용한 정기적인 검색이 더 나을 수 있습니다. 영구적으로 뜨거운 지수 - 비교 평가 Query vs Scan.

해당 인덱스를 쿼리하면 Expression Builder는 다음을 씁니다. 당신을 위한 KeyConditionExpression — 예: #s = :state AND begins_with(SK, :prefix) — 이름과 값이 올바르게 이스케이프되었습니다.

KeyConditionExpression     "#s = :state AND begins_with(SK, :prefix)"
ExpressionAttributeNames   { "#s": "order_state" }
ExpressionAttributeValues  { ":state": { "S": "PENDING" }, ":prefix": { "S": "ORD#2026-06-23" } }

기억해야 할 함정

관계형 본능 — "인덱스는 느리게 기록하고 약간만 기록합니다" — 양도. DynamoDB GSI는 수동적 구조가 아닌 처리량 종속성입니다. 크기를 줄이거나 덩어리진 키를 선택하면 제공되는 테이블에 역압이 가해집니다.

GSI에서 ConsumedWriteCapacityUnitsWriteThrottleEvents 시청하기 차원뿐만 아니라 Contributor Insights를 사용하여 인기 있는 항목을 찾습니다. 열쇠.

다음 단계

  • GSI vs LSI — GSI가 자체 용량과 다른 파티션 키.
  • Single-table design — 하나의 GSI를 다음에 과부하 핫 인덱스를 곱하지 않고도 다양한 패턴을 제공합니다.
  • Query vs Scan — 인덱스가 쓰기 비용만큼 가치가 없을 때.

Try DynoTable 테이블의 모든 GSI를 검사합니다 — 주요 스키마 및 품목 수 - 판매로 인해 빨간색으로 변하기 전에 색인을 쿼리합니다.

업데이트됨