입문5분 분량

DynamoDB 스캔이 느리고 비용이 많이 드는 이유

Scan테이블의 모든 항목을 읽고 나중에 필터링만 합니다. 그것은 SQL 근육 메모리에서 도달하는 작업과 조용히 수행되는 작업 남은 RDS 상자보다 지연 시간을 더 악화시키면서 청구서를 낭비하게 됩니다.

DynamoDB 스캔이 느리고 비용이 많이 드는 이유는 무엇입니까?

A ScanFilterExpression가 실행되기 전에 테이블의 모든 항목을 읽습니다. 얼마나 적은 행이 반환되더라도 전체 테이블을 읽으려면 비용을 지불해야 합니다. 테이블이 커지면 속도가 느려집니다. 수정은 거의 항상 Query 키로 이루어집니다. 키 주변의 액세스 패턴을 사용하여 DynamoDB가 대신 하나의 파티션에 접근하도록 합니다. 모든 것.

  • Scan는 매번 전체 테이블을 읽습니다. 결과 개수가 아닌 크기, 지불 금액과 소요 시간을 결정합니다.
  • FilterExpression는 비용에 대한 거짓말입니다. 읽기가 끝난 후에 실행됩니다. 측정되므로 12개 항목을 반환하면 1,200만 개를 읽는 비용이 청구될 수 있습니다.
  • Scan는 성장함에 따라 속도가 느려집니다. 키가 있는 Query는 평평하게 유지됩니다. 접촉합니다. 테이블 크기에 관계없이 하나의 파티션.
  • 수정은 거의 항상 튜닝이 아닌 모델링입니다. 일상적인 질문인데 열쇠가 없습니다.

스캔이 실제로 하는 일

SQL에서 왔기 때문에 SELECT * FROM events WHERE type = 'checkout'는 자유로워요 — 엔진에 인덱스가 있거나 없거나 둘 중 어느 쪽이든 행을 다시 가져옵니다. 에서 DynamoDB에는 이를 결정하는 쿼리 플래너가 없습니다.

Scan은 한 번에 1MB씩 전체 테이블을 순차적으로 탐색하고 각 테이블을 건네줍니다. FilterExpression 페이지로 이동하세요. 필터가 거부하는 내용은 여전히 읽혀집니다. 여전히 측정되어 있고 청구서에 남아 있습니다. (AWS: 테이블 스캔)

그것이 바로 함정입니다. 필터는 WHERE 절처럼 보이지만 결과 집합은 비용이 아닙니다. A Scan은 다음과 같은 경우에도 동일한 읽기 용량을 소비합니다. 필터가 없습니다. (AWS: 테이블 스캔)

읽기 단위 계산

DynamoDB 미터는 (RCU)로 표시됩니다. 하나의 RCU가 단일 구매 최대 4KB의 항목 읽기; 읽음 비용은 절반입니다. 더 큰 항목은 다음 4KB로 반올림됩니다. (AWS: 읽기/쓰기 용량 모드)

분석표 ProductEvents를 선택하세요. 각 행은 하나의 추적된 이벤트입니다.

PK  = "TENANT#acme"
SK  = "TS#2026-06-23T14:08:55Z#evt_9f3a"
attrs: eventType, sessionId, userId, payloadBytes

하나의 바쁜 테넌트 아래에서 각각 ~1KB의 2,000,000 이벤트를 보유한다고 가정해 보겠습니다. 당신 오늘 결제를 원해요. 반사적 움직임:

Scan ProductEvents
FilterExpression: eventType = "checkout"

해당 필터는 40개의 행을 반환할 수 있습니다. 하지만 Scan는 2,000,000개의 항목을 모두 읽었습니다. 먼저. 각각 ~1KB(4KB당 1RCU, 최종적으로는 4KB당 0.5RCU로 일관됨) 대략 250,000개의 RCU를 측정하고 ~2GB의 데이터를 페이징하여 40개의 아이템을 돌려주세요.

이제 액세스 패턴을 키로 모델링하고 대신 이를 모델링합니다.

Query ProductEvents
PK = "TENANT#acme"
AND SK begins_with "TS#2026-06-23"

이는 한 파티션의 일치하는 슬라이스만 읽습니다. 40개의 결제 행이 있는 경우 게다가 그날의 다른 이벤트는 최대 2MB에 달하므로 읽기 비용은 최대 2MB입니다. 2GB. 동일한 답변, 비용의 극히 일부 — 지연 시간은 일정하게 유지됩니다. 테이블이 커지면서.

스캔 대 쿼리, 측정

스캔 + 필터키 입력 쿼리
읽기테이블의 모든 항목SK로 좁혀진 파티션 1개
청구 용량필터 전의 전체 테이블슬라이스의 항목만
우리의 예~250,000 RCU(~2GB)수백 개의 RCU(~2MB)
대기 시간테이블 크기에 따라 증가테이블이 커짐에 따라 평평해짐
결과 개수비용에 대해 아무것도 결정하지 않음귀하가 지불하는 금액과 일치

표에 인코딩된 레슨: Scan에서는 결과 수와 청구서가 다음과 같이 표시됩니다. 관련이 없습니다. Query에서는 서로를 추적합니다.

스캔하기 전에 결정하세요

대부분의 우연한 질문은 하나의 질문에서 비롯됩니다: 파티션 이름을 지정할 수 있습니까? 필요합니까? 그렇다면 Query입니다. 그렇지 않은 경우 수정은 더 큰 필터가 아니라 핵심입니다.

다음은 흐름 형식의 결정입니다.

YesNoYesNo아이템을 읽어야파티션 키를 아는가?Query 파티션 하나GSI로 키를 잡을 있나?GSI 추가 QueryScan 최후 수단

경로는 거의 항상 Query에서 끝납니다. 그렇지 않은 경우에만 Scan로 넘어갑니다. 키 - 존재하거나 추가 가능 - 액세스 패턴에 적합합니다.

패턴이 실제적이고 반복적이지만 기본 테이블에서 해당 패턴에 키를 지정할 수 없는 경우 Global Secondary Index를 추가하라는 신호이므로 질문은 Query가 됩니다. 액세스 패턴을 중심으로 키를 모델링하는 것은 사전에 전체 게임 — single-table design을 참조하세요.

필터가 아닌 키 입력 쿼리를 작성합니다.

키 이상의 조건이 필요한 경우에는 키를 사용하지 않고 의도적으로 빌드하세요. 모든 것을 FilterExpression에 버리세요. 는 DynamoDB Expression Builder은 다음을 생성합니다. KeyConditionExpression 및 속성 자리 표시자가 있으므로 파티션이 및 정렬 키는 DynamoDB가 읽기를 측정하기 전이 아니라 읽기를 측정하기 전에 범위를 좁힙니다.

KeyConditionExpression: PK = :tenant AND begins_with(SK, :day)

스캔이 실제로 괜찮은 경우

Scan은 일상적인 쿼리에 대한 잘못된 기본값입니다. 이럴 때 딱 맞는 도구가 바로 당신은 정말로 "모든 것을 읽으십시오"를 의미합니다.

  • 일회성 내보내기 또는 백필이 수동으로 실행됩니다.
  • 전체 테이블이 몇 KB에 불과한 작은 구성/조회 테이블.
  • 의도적으로 전체 테이블을 페이지로 표시하는 백그라운드 작업. 그것들을 나누어 라. Segment / TotalSegments — a — 대신에 한 번의 긴 순차 크롤링. (AWS: 테이블 스캔)

그리고 PartiQL도 여러분을 구해 주지 않습니다. 키 조건절이 없는 SELECT * FROM ProductEvents WHERE eventType = 'checkout'은 곧장 Scan으로 컴파일됩니다. SQL 옷을 입은 같은 자충수입니다. (전체 분석은 Query vs Scan을 보세요.)

교차 항목 분석이 정말로 필요한 경우 — GROUP BY, JOIN, 집계 DynamoDB는 표현할 수 없습니다. DynoTable의 SQL Workbench는 이를 클라이언트 측에서 실행합니다. 전체 Scan로 테이블을 망치는 대신 제한된 결과 집합을 사용합니다.

다음 단계

두 패턴의 비용을 추정해 보세요. pricing calculator, 읽다 API 수준 대비의 경우 Query vs Scan, download DynoTable 이를 자신의 테이블과 비교하여 실행하고 시청하세요. 각 접근 방식이 실제로 읽는 항목 수입니다.

업데이트됨