DynamoDB에서 COUNT, SUM 및 집계하는 방법
DynamoDB에는 내장 집계가 정확히 하나 있습니다: Select=COUNT로 일치하는 항목을 세는
것입니다. 네이티브 SUM, AVG, MIN, MAX는 없습니다. 그리고 얻을 수 있는 그
개수조차 세는 모든 항목을 읽습니다(그리고 그에 대해 청구됩니다). 이 가이드는 실제로
지원되는 것, 사람들이 손을 뻗는 근사치, 그리고 필요할 때 테이블 위에서 실제
COUNT/SUM/AVG를 실행하는 방법을 다룹니다.
DynamoDB는 SUM, COUNT, 집계 함수를 수행할 수 있나요?
대부분은 안 됩니다. DynamoDB의 유일한 내장 집계는 Select=COUNT로, 일치하는 항목의 개수를 반환하지만 여전히 모든 항목을 읽습니다(그리고 그에 대해 청구됩니다). 네이티브 SUM, AVG, MIN, MAX는 없으며, PartiQL도 이를 추가하지 않습니다. GROUP BY를 동반한 진짜 집계가 필요하다면, 앱에서 접거나, 카운터를 유지하거나, DynoTable의 Workbench에서 SQL을 실행하세요.
- **
Select=COUNT**는 일치하는 항목의 개수를 반환하지만, DynamoDB는 그것을 만들기 위해 여전히 모든 항목을 읽습니다 — 저렴한 "count" 비용이 아니라 전체Scan/Query읽기 비용을 지불합니다. - 네이티브
SUM,AVG,MIN,MAX는 없습니다. DynamoDB의 읽기 연산은 항목을 반환하며, 그것들을 숫자로 접지 않습니다. PartiQL도 집계를 추가하지 않습니다. DescribeTable.ItemCount는 무료지만 근사치이며 "대략 6시간마다" 갱신됩니다 — 대시보드 타일에는 괜찮지만 정확해야 하는 것에는 부적합합니다.- 정확한
COUNT/SUM/AVG/MIN/MAX(그리고GROUP BY)를 원한다면 앱에서 집계하거나, 카운터를 유지하거나, DynoTable의 SQL Workbench에서 실행하세요(아래 참고).
항목 세기: Select=COUNT
Query와 Scan 모두 Select 파라미터를 받습니다. 이를 COUNT로 설정하면 응답이
항목 대신 개수를 담습니다:
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'응답은 두 개의 숫자를 줍니다(AWS: Counting the items in the results):
Count— "필터 표현식이(있는 경우) 적용된 후에 남은 항목의 수."ScannedCount— "ScanFilter가 적용되기 전에 평가된 항목의 수." 필터가 없으면ScannedCount는Count와 동일합니다.
파티션 키만 있고 그 안에서 중복을 세야 한다면, 전달하는 조건 + 필터는 바로
DynamoDB Expression Builder가 생성하는 것 —
위의 KeyConditionExpression, FilterExpression,
ExpressionAttributeNames/Values 맵 — 이며, JSON을 손으로 이스케이프할 필요가
없습니다.
큰 테이블을 세는 사람들을 무는 두 가지 함정이 더 있습니다:
- 1 MB 페이지 제한은 여전히 적용됩니다. "
Scan결과 집합의 크기가 1 MB보다 크면,ScannedCount와Count는 전체 항목의 부분 개수만 나타냅니다" (AWS Scan docs). 실제 숫자를 얻으려면LastEvaluatedKey→ExclusiveStartKey로 페이지를 넘기며 누적 합계를 유지해야 합니다 — DynamoDB 페이지네이션에서 다루는 것과 동일한 루프입니다. - 좁은
Query가Scan을 이깁니다.Query에 대한Select=COUNT는 전체 테이블이 아니라 대상 파티션의 항목만 계량합니다. 파티션 키를 지정할 수 있다면(기본 테이블이나 GSI), 거기서 세세요 — 이것은 세는 데 적용된 Query-vs-Scan 비용 격차입니다.
Select=COUNT vs ItemCount (그리고 왜 오래된 값인가)
DescribeTable은 ItemCount(그리고 TableSizeBytes)를 읽기 비용 없이 무료로
반환합니다. 함정은 API 레퍼런스 자체에
있습니다: "DynamoDB는 이 값을 대략 6시간마다 갱신합니다. 최근 변경 사항은 이 값에 반영되지
않을 수 있습니다." 따라서 테이블의 실제 상태보다 한참 뒤처질 수 있습니다.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| 정확성 | 정확 (일치하는 집합에 대해) | 근사 |
| 신선도 | 실시간 | 대략 6시간마다 갱신 |
| 비용 | 세는 모든 항목을 읽고 청구함 | 무료 (메타데이터) |
| 부분 집합 필터/세기 가능 | 예 (필터 표현식) | 아니요 — 전체 테이블만 |
테이블이 얼마나 큰지에 대한 대략적인 감각이나 대시보드 타일에는 ItemCount를 사용하세요.
정확하거나 필터링된, 또는 현재의 숫자가 필요할 때는 Select=COUNT를 사용하고 읽기 비용을
감수하세요. 진정으로 실시간이고 무료인 것이 필요하면, 카운터를 직접 추적하세요(아래
집계 패턴 참고).
네이티브 SUM/AVG/MIN/MAX가 없는 이유
DynamoDB의 읽기 연산은 항목을 반환합니다. 결과 집합을 스칼라로 접을 쿼리 플래너가 없으므로,
SUM이나 AVG를 계산할 대상도 없습니다. 세기는 API가 제공하는 유일한 접기이며,
Select=COUNT를 통해 이루어집니다.
PartiQL은 이를 바꾸지 않습니다.
PartiQL SELECT 문법은
SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …]이며,
여기서 표현식은 "* 와일드카드 또는 하나 이상의 속성 이름이나 문서 경로의 프로젝션
목록으로 형성된 프로젝션"입니다. 그 문법에는 집계 함수도 GROUP BY 절도 없으며 —
ORDER BY는 {{key}}를 받는데, 이는 "반환된 결과를 정렬하는 데 사용할 해시 키 또는
정렬 키"로 문서화되어 있습니다. 모든 PartiQL SELECT는 여전히 GetItem, Query, 또는
Scan으로 컴파일되므로, SELECT SUM(total) FROM "Orders"는 그냥 표현할 수 없습니다.
(PartiQL의 한계에 대해 더 알아보려면 PartiQL vs SQL 참고.)
집계 패턴 (카운터, 스트림, 앱 측)
DynamoDB가 대신 집계해 주지 않으므로, 확립된 패턴들은 작업을 다른 곳으로 밀어냅니다:
- 유지되는 카운터 항목. 전용 항목(예:
PK = "STATS#orders")을 두고 모든 쓰기마다UpdateItem으로 숫자 속성에ADD합니다. 그러면 집계를 읽는 것은 단일GetItem입니다 — 정확하고 저렴하지만, 증가 로직과 그 일관성, 그리고 하나의 카운터가 두들겨 맞을 때의 경합을 직접 책임져야 합니다. - DynamoDB Streams → 집계기. 스트림을 활성화하고 항목이 변경될 때 누적
합계(개수, 합계)를 갱신하는 Lambda에 연결합니다.
AWS Streams docs에
따르면, 각 레코드가
NEW_AND_OLD_IMAGES— "항목의 새 이미지와 이전 이미지 둘 다" — 를 담도록 스트림의StreamViewType을 구성할 수 있으며, 이는 재스캔 없이SUM스타일 집계를 최신으로 유지하기에 충분합니다. 스트림 레코드는 24시간 수명의 적용을 받으므로("샤드 내의 스트림 레코드는 24시간 후 자동으로 제거됩니다"), 소비자가 따라잡아야 합니다. - 앱 측 접기. 일치하는 항목을 페이지로 넘기며 직접 코드에서
SUM/AVG/MIN/MAX를 누적합니다. 올바르지만, 매번 모든 항목을 읽으며(그리고 청구되며) —Select=COUNT와 동일한 비용 프로필에 데이터 전송이 더해집니다. - 분석으로 오프로드. 무겁거나 즉석의 분석 집계의 경우, 테이블을 S3로 내보내 Athena로 쿼리하거나, 웨어하우스로 스트리밍합니다. AWS export-to-S3 docs에 따르면, 내보내기는 "읽기 용량 단위를 소비하지 않으며" "Athena 같은 AWS 서비스를 사용하여 분석과 복잡한 쿼리를 수행"할 수 있게 합니다 — 요청별 집계를 넘어선 후 AWS가 권장하는 경로입니다.
각각은 단순성을 쓰기 시점의 부기(카운터, 스트림) 또는 읽기 시점의 비용(앱 측 스캔)과
맞바꿉니다. 어떤 패턴도 DynamoDB 자체가 SUM을 무료로 계산하게 만들지는 않습니다. 이
트레이드오프의 그룹화 버전 — 전체 테이블이 아니라 키별로 집계하는 것 — 은 자체
가이드입니다: DynamoDB GROUP BY.
DynoTable의 SQL Workbench에서 COUNT/SUM/AVG 실행하기
페이지네이션 스캔 루프나 Lambda를 작성하지 않고 그냥 답이 필요할 때 — "OPEN 주문이 몇 개이고 그 총액은 얼마인가" — DynoTable의 SQL Workbench가 실제 집계를 실행합니다. DynamoDB의 실제 Query/Scan 런타임을 통해 테이블을 구체화한 다음, 그 위에서 전체 SQL을 실행합니다: DynamoDB의 액세스 패턴 규칙 안에서의 SQL.
-- Runs in the DynoTable Workbench (NOT in PartiQL):
SELECT status,
COUNT(*) AS orders,
SUM(total) AS revenue,
AVG(total) AS avg_order,
MIN(total) AS smallest,
MAX(total) AS largest
FROM orders
GROUP BY status
ORDER BY revenue DESC이것이 COUNT, SUM, AVG, MIN, MAX, GROUP BY, ORDER BY — DynamoDB도
PartiQL도 표현할 수 없는 것들 — 을 한 문장에 담은 것입니다. 이것은
SQL for DynamoDB와 동일한 분석적 지렛대이며, 완전한 그룹화
이야기는 DynamoDB GROUP BY를 참고하세요.
Workbench는 그 아래의 액세스 모델에 대해 정직하며, 가짜 Postgres가 아닙니다:
- 행은 여전히 DynamoDB의 실제 Query/Scan을 통해 들어옵니다. 전체 테이블에 대한
GROUP BY는 그 아래에서 여전히Scan입니다 — Workbench는 그 비용을 숨기지 않고 드러내며, 동일한 Query-vs-Scan 트레이드오프입니다. - 집계는 행이 도착한 후 구체화된 스칼라 속성에 대해 실행됩니다.
FAQ
스캔 없이 DynamoDB에서 항목을 셀 수 있나요?
정확히는 아닙니다. 정확하고 현재의 개수를 얻으려면 항목을 읽어야 합니다 —
Select=COUNT는 여전히 세는 모든 항목을 계량합니다. 스캔이 없는 유일한 옵션은 근사치인
DescribeTable.ItemCount(대략 6시간마다 갱신)이거나, 매 쓰기마다 직접 유지하는 카운터
항목입니다.
GSI로 항목을 어떻게 세나요?
인덱스에 대해 Select=COUNT로 Query(또는 Scan)를 실행하세요. 좁은 GSI 파티션을 통한
세기는 그 인덱스 파티션의 항목만 읽기 때문에 기본 테이블을 스캔하는 것보다 훨씬 저렴합니다
— 필요한 count를 중심으로 인덱스를 모델링하세요.
DescribeTable.ItemCount는 정확한가요?
근사치입니다.
API 레퍼런스는
DynamoDB가 ItemCount와 TableSizeBytes를 "대략 6시간마다" 갱신하며 "최근 변경 사항은
이 값에 반영되지 않을 수 있다"고 명시합니다. 정확하거나 실시간 숫자가 중요한 곳에서는 쓰지
마세요.
DynamoDB는 SUM이나 AVG를 할 수 있나요?
네이티브로도, PartiQL로도 안 됩니다 —
PartiQL SELECT 문법에는
집계 함수가 없습니다. 애플리케이션에서 집계하거나, 카운터를 유지하거나(선택적으로
DynamoDB Streams를 통해), DynoTable의 SQL Workbench에서 SUM/AVG를 실행하세요.
Count와 ScannedCount의 차이는 무엇인가요?
ScannedCount는 DynamoDB가 필터 전에 평가한 항목의 수이고, Count는 그 후에 남은 수입니다.
필터 표현식이 없으면 둘은 같습니다. 둘 사이의 큰 격차는 비효율적인 count를 의미합니다.
스캔 루프를 작성하지 않고 DynamoDB 데이터를 합산하거나, 평균 내거나, 그룹화해야 하나요? DynoTable 다운로드 후 Workbench 탭에서 실행하세요. 먼저 클라이언트를 비교하고 계신가요? 평범한 DynamoDB GUI와 비교해 어디에 위치하는지 확인해 보세요.