Clave primaria compuesta en DynamoDB
Una clave primaria compuesta son dos atributos: una clave de partición y una clave de ordenación. La clave de partición decide dónde vive un item; la clave de ordenación ordena los items dentro de esa partición.
Si vienes de SQL, piénsalo menos como una columna id única y más como
GROUP BY partition, ORDER BY sort integrado en la propia tabla.
¿Qué es una clave primaria compuesta en DynamoDB?
Una clave primaria compuesta en DynamoDB combina dos atributos: una clave de partición y una clave de ordenación. La clave de partición decide en qué partición física vive un item; la clave de ordenación ordena los items dentro de esa partición. Juntas forman la identidad única del item y permiten que un solo Query devuelva un rango ordenado en lugar de un único item.
- Dos partes, dos trabajos. La clave de partición enruta el item a una partición física; la clave de ordenación ordena cada item que comparte esa clave de partición.
- La unicidad es el par. Dos items pueden compartir un valor de clave de partición siempre que sus claves de ordenación difieran — así es como una partición contiene muchas filas.
- La clave de ordenación lo es todo. Es lo que permite que un
Querydevuelva un rango (>=,between,begins_with) en lugar de un solo item, sinScan. - Las claves deben ser escalares. Las claves de partición y de ordenación solo pueden ser cadena, número o binario — sin mapas, sin listas (Documentación de AWS).
Clave simple vs clave compuesta
Una clave primaria simple es solo una clave de partición. Identifica un item de
forma única, y lo lees de vuelta con GetItem. Eso es todo — sin lecturas de rango,
sin "dame los N más recientes".
Una clave compuesta añade la clave de ordenación, y esa única adición es lo que hace que DynamoDB se sienta como una base de datos en lugar de un mapa hash.
| Clave simple | Clave compuesta | |
|---|---|---|
| Atributos | Solo clave de partición | Clave de partición + clave de ordenación |
| Unicidad | Valor de la clave de partición | El par de valores |
| Múltiples items por partición | No | Sí |
Query de un rango | No (solo GetItem) | Sí (begins_with, between, >) |
| Encaje natural | Búsqueda por id | Series temporales, uno a muchos, historial |
Modela una tabla de lecturas de sensores
Supón que recoges muestras de temperatura de una flota de sensores de campo. El patrón de acceso es "obtén las lecturas de un dispositivo, las más nuevas primero, dentro de una ventana de tiempo". Eso es una clave compuesta de manual.
Usa el id del dispositivo como clave de partición y la marca de tiempo de la lectura como clave de ordenación:
| deviceId | readingTs | tempC | humidity |
|---|---|---|---|
| DEV#a1b2 | 2026-06-23T08:00:00Z | 21.4 | 48 |
| DEV#a1b2 | 2026-06-23T08:05:00Z | 21.7 | 47 |
| DEV#a1b2 | 2026-06-23T08:10:00Z | 22.1 | 46 |
| DEV#c9d8 | 2026-06-23T08:00:00Z | 19.8 | 55 |
Las tres lecturas de DEV#a1b2 aterrizan en la misma partición, almacenadas
físicamente juntas y ordenadas por readingTs.
AWS llama a la clave de partición el atributo hash y a la clave de ordenación el atributo range — la clave de ordenación es un rango dentro del que puedes escanear (Documentación de AWS).
Aquí está cómo los items colapsan en una sola item collection bajo cada clave de partición:
Un Query contra la clave de partición lee cada lectura de ese dispositivo, ya en orden
de marca de tiempo — sin ordenar en el cliente, sin un segundo viaje de ida y vuelta.
Consulta el rango, no lo escanees
Como readingTs es una cadena ISO-8601, se ordena lexicográficamente de la misma forma
que se ordena cronológicamente. Así que una lectura de ventana de tiempo es un rango de
condición de clave, no un filtro:
Query
deviceId = "DEV#a1b2"
readingTs BETWEEN "2026-06-23T08:00:00Z" AND "2026-06-23T08:10:00Z"
Eso es un KeyConditionExpression — estrecha la lectura antes de que DynamoDB
devuelva los datos, así que pagas solo por los items de la ventana. Un
FilterExpression se ejecuta después de la lectura y te factura por todo lo que
escaneó; ese es el error del Scan en miniatura.
La expresión en sí, con placeholders y valores tipados, es engorrosa de escribir a mano.
Constrúyela visualmente con el
DynamoDB Expression Builder y copia el
KeyConditionExpression exacto en tu llamada al SDK.
Diseña la clave de ordenación a propósito
La clave de ordenación no es metadato gratis — es la única palanca para lecturas de rango, así que moldéala a tus consultas.
- Usa una marca de tiempo ordenable. Las cadenas ISO-8601 o los números epoch rellenados con ceros se ordenan correctamente; las fechas localizadas en crudo no.
- Ponle un prefijo para overloading de uno a muchos. Una clave de ordenación como
READING#2026-06-23T08:00:00Zte permite mezclar tipos de entidad bajo una partición y cortarlos conbegins_with. Esa es la costura hacia el single-table design. - Pon la dimensión de alta cardinalidad en la clave de partición. El id del sensor
tiene miles de valores, así que reparte las escrituras de forma equitativa. Una clave
de partición de baja cardinalidad (digamos,
region) crea una partición caliente.
Cuándo una clave compuesta te muerde
Es un compromiso, no una comodidad. La trampa: eliges una clave de partición, despliegas, y luego descubres un patrón de acceso que necesita una agrupación diferente — "todas las lecturas por encima de 30°C en toda la flota".
La tabla base no puede responder eso; la clave de partición es fija. Tus opciones son un global secondary index con una clave diferente, o reestructurar.
Enumera tus lecturas antes de comprometer el esquema de claves. Cambiar una clave
primaria significa una migración de tabla, no un ALTER TABLE.
Próximos pasos
Las claves compuestas son la base sobre la que se asientan las item collections, las relaciones de uno a muchos y la mayoría de los diseños útiles de índices — lee single-table design y GSI vs LSI a continuación para ver a dónde llevan.
Esboza tu KeyConditionExpression en el
DynamoDB Expression Builder, luego
prueba DynoTable para navegar tus particiones reales y ver el orden de
ordenación alinearse contra tus propias tablas.