Java(AWS SDK v2)의 DynamoDB Scan
scanPaginator는 LastEvaluatedKey를 대신 처리해 주며, 대부분이 그다음으로 손대는 손잡이 하나인 .limit(...)은 같은 Scan을 더 느리고 살짝 더 비싸게 만듭니다. Scan을 아예 피해야 할 때는 Query vs. Scan을 참조하세요.
코드
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
public class ScanExample {
public static void main(String[] args) {
try (DynamoDbClient ddb = DynamoDbClient.builder()
.region(Region.US_EAST_1)
.build()) {
Map<String, String> names = new HashMap<>();
names.put("#filter0", "Year");
Map<String, AttributeValue> values = new HashMap<>();
values.put(":filterValue0", AttributeValue.builder().n("2010").build());
ScanRequest request = ScanRequest.builder()
.tableName("Music")
.filterExpression("#filter0 >= :filterValue0")
.expressionAttributeNames(names)
.expressionAttributeValues(values)
.build();
List<Map<String, AttributeValue>> items = new ArrayList<>();
for (ScanResponse page : ddb.scanPaginator(request)) {
items.addAll(page.items());
}
System.out.println("Matched " + items.size() + " items");
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
}
}
}.limit(25)는 요청 3번을 25번으로 바꾸고 비용도 늘립니다
픽스처에는 각각 약 3.9 KB인 600곡이 있고 그중 8곡이 조건에 맞습니다. 예제를 그대로 실행한 다음, .limit(25)를 붙여 다시 실행해 보세요:
| 요청 형태 | 왕복 횟수 | 읽기 단위 | 반환된 항목 |
|---|---|---|---|
| 그대로 | 3 | 284.5 | 8 |
.limit(25) | 25 | 288.0 | 8 |
용량은 페이지 단위로, 4 KB 경계까지 올림해 부과됩니다. 그래서 1 MB짜리 읽기 하나를 작은 24개로 쪼개면 그 올림을 24번 치릅니다. 25번째 요청이 또 다른 놀라움입니다. 24번째 페이지가 테이블을 다 훑고도 LastEvaluatedKey를 반환했고, 그래서 페이지네이터가 한 번 더 물어 scannedCount=0을 받았습니다. DynamoDB는 "데이터가 더 없다"를 짧은 페이지가 아니라 그 키를 생략하는 것으로 알리며, Limit 경계에서는 아직 알지 못합니다.
.limit(...)은 라이브 테이블을 스로틀링시키고 싶지 않은 백그라운드 작업을 위한 용량 평탄화 손잡이입니다. Scan을 더 싸거나 더 짧게 만드는 방법이 아닙니다.
별칭은 취향이 아닙니다
#filter0을 빼고 Year로 직접 필터링하면 SDK가 awsErrorDetails()를 통해 이것을 드러냅니다:
DynamoDbException / ValidationException /
Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: Year
/ http 400Year는 573개 예약어 중 하나입니다. 이 SDK의 모든 페이지네이터 오류와 마찬가지로, scanPaginator(request)를 호출할 때가 아니라 for 루프의 첫 반복에서 도착하므로 try가 루프를 감싸야 합니다.
2026-07-28에 OpenJDK 26.0.1에서 software.amazon.awssdk:dynamodb 2.49.4로 DynamoDB Local(amazon/dynamodb-local)을 상대로 측정했습니다.
설명
- 처음 두 페이지는 항목을 0개 반환합니다. 이 필터에서 페이지별 결과는 0, 0, 8이고 읽기 단위는 128.5, 128.5, 27.5입니다.
filterExpression은 읽기 후에 실행되므로 그 빈 응답 두 개도 제값을 다 치르며,if (page.items().isEmpty()) break같은 코드는 빈 테이블이라고 보고합니다. ddb.scanPaginator(request).items()— 페이지들을 하나의Iterable<Map<String, AttributeValue>>로 평탄화하고 뒤에서 페이지를 넘겨 주므로, 항목만 필요할 때 중첩 루프를 없애 줍니다.SdkIterable이라.stream()도 동작합니다 — 여기서는.items().stream().count()가 8을 반환합니다.ScanIterable은 반복할 때마다 Scan을 다시 실행합니다. 캐시가 아니라 지연 평가입니다. 같은 객체를 두 번 순회하면 요청도 두 번 보내고 요금도 두 번 부과됩니다. 예제처럼 한 번에List로 비워 내세요.- 빌더에서 숫자는
String입니다. DynamoDB가 숫자를 십진 텍스트로 전송하기 때문에AttributeValue.builder().n("2010")은java.lang.String을 받습니다.int를 넘기면 컴파일되지 않습니다. .segment(...)/.totalSegments(...)— 전체 테이블 Scan을 워커별로 각자의 페이지네이터와 함께 나눕니다. 벽시계 시간은 나뉘고 소비 용량은 같습니다.
시각적으로 해보기
예약어 검사기는 여러분의 속성 이름을 AWS 전체 목록에 대고 검사해 ExpressionAttributeNames 맵을 돌려줍니다. Year, Name, Size, Status가 전부 예약어라는 것을 ValidationException 하나씩 겪으며 배우는 것보다 빠릅니다.
필터를 ScanRequest에 엮기 전에 실제 테이블을 상대로 시험해 보려면, DynoTable을 다운로드해서 결과를 그리드로 넘겨 보세요.
관련 예제
- Go의 DynamoDB Scan — AWS SDK for Go v2로 수행하는 동일한 Scan.
- Java의 DynamoDB Query — 보통 손을 뻗어야 할 더 저렴한 읽기.
- Query vs. Scan — (드물게)
Scan이 정당화되는 때. - 내 DynamoDB Scan은 왜 느리고 비쌀까요? — 비용 모델과 그것을 피하는 방법.
- DynamoDB ProvisionedThroughputExceededException — 전체 테이블 Scan이 프로비저닝된 테이블의 용량에 무슨 일을 하는지.
- DynamoDB ThrottlingException — 또 다른 스로틀링과 지수 백오프가 그것을 처리하는 방식.
참고 자료
- Scan — Amazon DynamoDB API Reference
- Use Scan with an AWS SDK or CLI — Amazon DynamoDB Developer Guide
- DynamoDbClient — AWS SDK for Java 2.x API Reference
- ScanRequest — AWS SDK for Java 2.x API Reference
- Scanning tables — Amazon DynamoDB Developer Guide
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide