Cómo hacer COUNT, SUM y agregados en DynamoDB
DynamoDB tiene exactamente un agregado incorporado: contar los elementos que coinciden con
Select=COUNT. No hay SUM, AVG, MIN ni MAX nativos. E incluso el recuento
que puedes obtener lee (y factura) cada elemento que contó. Esta guía cubre lo que
realmente se admite, las aproximaciones a las que recurre la gente y cómo ejecutar
COUNT/SUM/AVG reales sobre una tabla cuando los necesitas.
¿Puede DynamoDB hacer SUM, COUNT y funciones de agregación?
Mayormente no. El único agregado incorporado de DynamoDB es Select=COUNT, que devuelve recuentos de elementos coincidentes pero aún lee (y factura) cada elemento. No hay SUM, AVG, MIN ni MAX nativos, y PartiQL tampoco añade ninguno. Para agregados reales con GROUP BY, agrégalos en tu aplicación, mantén un contador o ejecuta SQL en el Workbench de DynoTable.
Select=COUNTdevuelve el número de elementos coincidentes, pero DynamoDB aún lee cada elemento para producirlo — pagas el costo de lectura completo delScan/Query, no un costo de "recuento" barato.- No hay
SUM,AVG,MINniMAXnativos. Las operaciones de lectura de DynamoDB devuelven elementos; no los pliegan en un número. PartiQL tampoco añade agregados. DescribeTable.ItemCountes gratis pero aproximado y se actualiza solo "aproximadamente cada seis horas" — bien para un mosaico de panel, incorrecto para cualquier cosa exacta.- Para
COUNT/SUM/AVG/MIN/MAXexactos (conGROUP BY), agrega en tu aplicación, mantén un contador o ejecútalo en el SQL Workbench de DynoTable (abajo).
Contar elementos: Select=COUNT
Tanto Query como Scan aceptan un parámetro Select. Ponlo en COUNT y la
respuesta lleva los recuentos en lugar de los elementos:
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'La respuesta te da dos números (AWS: Contar los elementos en los resultados):
Count— "el número de elementos que quedan, después de aplicar una expresión de filtro (si está presente)".ScannedCount— "el número de elementos evaluados, antes de aplicar cualquierScanFilter". Sin filtro,ScannedCountes igual aCount.
Si solo tienes la y necesitas contar duplicados dentro de ella, la
condición + filtro que pasas es exactamente lo que genera el
Generador de expresiones de DynamoDB — la
FilterExpression y los mapas ExpressionAttributeNames/Values de arriba, más la
KeyConditionExpression cuando cuentas dentro de una partición mediante Query — sin
escapar el JSON a mano.
Dos escollos más que muerden a quienes cuentan tablas grandes:
- El límite de página de 1 MB sigue aplicando. "Si el tamaño del conjunto de resultados del
Scanes mayor que 1 MB,ScannedCountyCountrepresentan solo un recuento parcial del total de elementos" (documentos de Scan de AWS). Tienes que paginar retroalimentando elLastEvaluatedKeyde cada respuesta como elExclusiveStartKeyde la siguiente solicitud, manteniendo un total acumulado para obtener el número real — el mismo bucle cubierto en paginación de DynamoDB. - Una
Queryestrecha supera a unScan.Select=COUNTen unaQuerycontabiliza solo los elementos de la partición objetivo, no de toda la tabla. Si puedes fijar una clave de partición (tabla base o un GSI), cuenta ahí — es la brecha de costo Query frente a Scan aplicada al recuento.
Select=COUNT frente a ItemCount (y por qué está obsoleto)
DescribeTable devuelve un ItemCount (y TableSizeBytes) gratis, sin
costo de lectura. La trampa está en la
propia referencia de la API:
"DynamoDB actualiza este valor aproximadamente cada seis horas. Es posible que los cambios recientes no
se reflejen en este valor". Así que puede quedarse muy por detrás del estado real de tu tabla.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Exactitud | Exacto (para el conjunto coincidente) | Aproximado |
| Frescura | En vivo | Actualizado ~cada 6 horas |
| Costo | Lee + factura cada elemento contado | Gratis (metadatos) |
| Puede filtrar / contar un subconjunto | Sí (expresión de filtro) | No — solo toda la tabla |
Usa ItemCount para una comprobación rápida de "qué tan grande es esta tabla" o un mosaico de panel.
Usa Select=COUNT cuando necesites un número exacto, filtrado o actual — y acepta
el costo de lectura. Para algo verdaderamente en vivo y gratis, lleva un contador tú mismo
(consulta Patrones de agregación abajo).
Por qué no hay SUM/AVG/MIN/MAX nativos
Las operaciones de lectura de DynamoDB devuelven elementos. No hay planificador de consultas que pliegue un
conjunto de resultados en un escalar, así que no hay nada con lo que calcular un SUM o AVG. Contar es
el único pliegue que ofrece la API, mediante Select=COUNT.
PartiQL no cambia esto. La
gramática de SELECT de PartiQL
es SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …],
donde la expresión es "una proyección formada a partir del comodín * o una lista de
proyección de uno o más nombres de atributo o rutas de documento". No hay función de agregación
ni cláusula GROUP BY en esa gramática — y ORDER BY toma una {{key}},
documentada como "una clave hash o una clave de ordenación para ordenar los resultados devueltos". Cada
SELECT de PartiQL aún se compila en un GetItem, Query o Scan, así que
SELECT SUM(total) FROM "Orders" simplemente no es expresable. (Más sobre el techo de PartiQL
en PartiQL frente a SQL.)
Patrones de agregación (contadores, streams, del lado de la aplicación)
Como DynamoDB no agregará por ti, los patrones establecidos empujan el trabajo a otro lugar:
- Elemento contador mantenido. Mantén un elemento dedicado (p. ej.
PK = "STATS#orders") y hazADDa un atributo numérico en cada escritura con unUpdateItem. Leer el agregado es entonces un soloGetItem— exacto y barato, pero tú eres dueño de la lógica de incremento, su coherencia y la contención si un contador recibe muchos golpes. - alimentando un agregador. Habilita un stream y conéctalo a una Lambda que
actualice los totales acumulados (recuentos, sumas) a medida que cambian los elementos. Según los
documentos de Streams de AWS,
puedes configurar el
StreamViewTypedel stream para que cada registro lleve lasNEW_AND_OLD_IMAGES— "tanto la imagen nueva como la antigua del elemento" — suficiente para mantener actualizados los agregados de estiloSUMsin volver a escanear. Los registros del stream están sujetos a una vida útil de 24 horas ("los registros del stream dentro de un fragmento se eliminan automáticamente después de 24 horas"), así que el consumidor tiene que mantener el ritmo. - Pliegue del lado de la aplicación. Pagina a través de los elementos coincidentes y acumula el
SUM/AVG/MIN/MAXen tu propio código. Correcto, pero lee (y factura) cada elemento cada vez — el mismo perfil de costo queSelect=COUNT, más la transferencia de datos. - Descargar a análisis. Para agregación analítica pesada o ad hoc, exporta la tabla a S3 y consúltala con Athena, o transmítela a un almacén de datos. Según los documentos de exportación a S3 de AWS, exportar "no consume unidades de capacidad de lectura" y te permite "realizar análisis y consultas complejas usando servicios de AWS como Athena" — la ruta recomendada por AWS una vez que has superado la agregación por solicitud.
Cada uno intercambia simplicidad por o bien contabilidad en tiempo de escritura (contadores, streams) o
costo en tiempo de lectura (escaneos del lado de la aplicación). Ningún patrón hace que DynamoDB mismo calcule un SUM
gratis. La versión con agrupación de esta compensación — agregar por clave en lugar de
sobre toda la tabla — tiene su propia guía:
DynamoDB GROUP BY.
Ejecutar COUNT/SUM/AVG en el SQL Workbench de DynoTable
Cuando solo necesitas la respuesta — "cuántos pedidos OPEN hay y cuál es su total" —
sin escribir un bucle de escaneo con paginación ni una Lambda, el SQL Workbench de DynoTable
ejecuta agregados reales. Materializa tus tablas a través del runtime real de
Query/Scan de DynamoDB, luego ejecuta un único SELECT encima — agregados,
GROUP BY, HAVING, DISTINCT:
SQL dentro de las reglas de patrones de acceso de DynamoDB.
-- 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 DESCEso es COUNT, SUM, AVG, MIN, MAX, GROUP BY y ORDER BY sobre un
agregado calculado — nada de lo cual DynamoDB ni PartiQL pueden expresar (el
ORDER BY de PartiQL se limita a atributos de clave) — en una sola sentencia. Esta es la misma
cuña analítica que SQL para DynamoDB; para la historia
completa de la agrupación consulta DynamoDB GROUP BY.
El Workbench es honesto sobre el modelo de acceso subyacente, no un pseudo-Postgres:
- Las filas aún vienen a través del Query/Scan real de DynamoDB. Un
GROUP BYsobre toda una tabla sigue siendo unScanpor debajo — el Workbench expone ese costo en lugar de ocultarlo, la misma compensación Query frente a Scan. - Los agregados se ejecutan sobre los atributos escalares materializados después de que las filas aterrizan.
FAQ
¿Puedo contar elementos en DynamoDB sin escanear?
No exactamente. Para un recuento exacto y actual debes leer los elementos —
Select=COUNT aún contabiliza cada elemento contado. Las únicas opciones sin escaneo son el
aproximado DescribeTable.ItemCount (actualizado ~cada 6 horas) o un elemento contador que
mantengas tú mismo en cada escritura.
¿Cómo cuento elementos por un GSI?
Ejecuta Query (o Scan) contra el índice con Select=COUNT. Contar mediante una
partición estrecha de GSI es mucho más barato que escanear la tabla base, porque solo
lees los elementos de esa partición del índice — modela el índice en torno al recuento que necesitas.
¿Es preciso DescribeTable.ItemCount?
Es aproximado. La
referencia de la API
indica que DynamoDB actualiza ItemCount y TableSizeBytes "aproximadamente cada seis
horas", y "es posible que los cambios recientes no se reflejen en este valor". No lo uses donde
importe un número exacto o en vivo.
¿Puede DynamoDB hacer SUM o AVG?
No de forma nativa, y no en PartiQL — la
gramática de SELECT de PartiQL
no tiene funciones de agregación. Agrega en tu aplicación, mantén un contador
(opcionalmente mediante DynamoDB Streams) o ejecuta el SUM/AVG en el SQL
Workbench de DynoTable.
¿Cuál es la diferencia entre Count y ScannedCount?
ScannedCount es cuántos elementos evaluó DynamoDB antes de tu filtro; Count es
cuántos quedan después. Son iguales cuando no hay expresión de filtro. Una gran
brecha entre ellos significa un recuento ineficiente.
¿Necesitas sumar, promediar o agrupar tus datos de DynamoDB sin escribir un bucle de escaneo? Descarga DynoTable y ejecútalo en una pestaña del Workbench. ¿Comparando clientes primero? Mira dónde queda frente a una GUI de DynamoDB corriente.