Claves de ordenación compuestas en DynamoDB
Una clave primaria compuesta es una clave de partición más una clave de
ordenación. El truco que la hace poderosa es lo que pones dentro de la clave de
ordenación: codifica una jerarquía como una sola cadena delimitada, y un único
Query lee un subárbol entero en orden de ordenación — sin joins, sin recursión, sin
un segundo viaje de ida y vuelta.
¿Cómo funcionan las claves de ordenación compuestas en DynamoDB?
Una clave de ordenación compuesta empaqueta una jerarquía en una sola cadena delimitada — root/photos/2026/ — que DynamoDB almacena en orden de bytes UTF-8. Como la disposición ya coincide con el árbol, un único Query con begins_with(SK, "root/photos/") lee un subárbol entero en orden de ruta. Sin joins, sin recursión, sin un segundo viaje de ida y vuelta — solo un scan de prefijo sobre una porción contigua.
- La clave de ordenación es una cadena ordenable, no solo un ID. Empaqueta una
ruta dentro —
root/photos/2026/— y DynamoDB almacena los items de la partición en orden de bytes UTF-8 automáticamente. - Un delimitador convierte las coincidencias de prefijo en lecturas de subárbol.
begins_with(SK, "root/photos/")devuelve todos los descendientes de esa carpeta en una sola consulta. - Las claves de ordenación admiten condiciones de rango, no filtros arbitrarios.
Tienes
begins_with,between,>,<— diseña la clave para que la lectura que necesitas sea un prefijo o un rango, no unScan. - El delimitador es crítico. Elige uno que no pueda aparecer en un segmento de ruta, o dos ramas no relacionadas colisionarán.
Por qué la clave de ordenación lo es todo
Si vienes de SQL, modelarías un árbol de carpetas con un self-join parent_id y lo
recorrerías recursivamente — una consulta por nivel. En DynamoDB eso es un error de
diseño N+1 contra un almacén clave-valor que no tiene joins.
DynamoDB almacena cada item bajo una clave de partición ordenado por su clave de ordenación, en orden de bytes UTF-8 para cadenas (AWS: Query key conditions). Así que si tu clave de ordenación es la ruta, la disposición física ya coincide con el árbol. Una lectura se convierte en un scan de prefijo sobre una porción contigua — no en un recorrido de grafo.
Ese es el cambio: la clave de ordenación no es un identificador que coincides exactamente. Es una dirección ordenable. Diséñala y la consulta sale gratis.
Modela un árbol de sistema de archivos
Supón que almacenas árboles de archivos por cuenta. Un disco por cuenta es la partición natural; la ruta dentro de él es la clave de ordenación.
| PK | SK | node_type | bytes |
|---|---|---|---|
| DRIVE#a91 | root/ | folder | - |
| DRIVE#a91 | root/photos/ | folder | - |
| DRIVE#a91 | root/photos/2026/ | folder | - |
| DRIVE#a91 | root/photos/2026/beach.jpg | file | 284910 |
| DRIVE#a91 | root/photos/2026/sunset.jpg | file | 512004 |
| DRIVE#a91 | root/docs/ | folder | - |
| DRIVE#a91 | root/docs/taxes.pdf | file | 88210 |
Dos convenciones originales hacen el trabajo aquí:
PK = DRIVE#<account>mantiene todo el árbol de una cuenta en una sola item collection, así que cualquier lectura de subárbol es unQueryde una sola partición.SKes la ruta completa con una/final en las carpetas. La barra final es deliberada — hace que una carpeta se ordene antes que sus propios hijos y mantieneroot/photos/distinto de un archivo hermano llamadoroot/photos.
Lee un subárbol en una consulta
Lista todo lo que hay bajo root/photos/ — carpeta, subcarpetas y archivos,
recursivamente:
Query
KeyConditionExpression = PK = :drive AND begins_with(SK, :prefix)
:drive = "DRIVE#a91"
:prefix = "root/photos/"
Eso devuelve root/photos/, root/photos/2026/, beach.jpg y sunset.jpg — en
orden de ruta, en una sola lectura facturada. Pagas solo por los items de esa porción,
no por todo el disco.
En DynoTable, ejecutas exactamente esta consulta begins_with contra la clave de
ordenación de ruta y la carpeta junto con sus descendientes vuelven en orden de ruta —
sin sintaxis de placeholders que escribir a mano.
¿Necesitas el KeyConditionExpression en bruto (nombres, valores y begins_with) para
tu propio código? Constrúyelo y cópialo en el
DynamoDB Expression Builder.

Lista un nivel, no todo el subárbol
begins_with te da la lectura recursiva. Para un listado de directorio no recursivo
— los hijos inmediatos de root/photos/ y nada más profundo — almacena un atributo de
profundidad y añade un rango de clave de ordenación más un filtro, o divide la ruta
en un GSI parent. La versión más simple: mantén un atributo parent (root/photos/)
y un GSI con clave sobre él.
La idea: una clave de ordenación responde preguntas de prefijo y rango de forma
barata. "Solo hijos directos" es una pregunta diferente — modélala explícitamente en
lugar de esperar que un FilterExpression la haga eficiente. Un filtro se ejecuta
después de la lectura y pagas por cada item que descarta.
Elige el delimitador con cuidado
El delimitador forma parte de tu contrato de datos. Dos reglas:
- Nunca debe aparecer dentro de un segmento de ruta. Si los nombres de archivo
pueden contener
/,/es el delimitador equivocado — un archivo llamadoa/bes indistinguible de una carpetaaque contieneb. Elige un byte reservado (algunos equipos usan#o un carácter de control) y prohíbelo en los segmentos. - Cuidado con el orden de ordenación en los límites.
/(0x2F) se ordena antes que los dígitos y las letras, que suele ser lo que quieres para el orden del árbol. Cambia el delimitador y cambias la ordenación — verifícalo contra datos reales.
Clave de ordenación compuesta vs. un atributo de ordenación separado
Clave de ordenación compuesta (root/photos/2026/x) | ID de ordenación simple + atributo parent | |
|---|---|---|
| Lectura de subárbol | Una consulta begins_with | Consultas recursivas (N+1) o un recorrido de GSI |
| Ordenación | Orden de ruta, gratis | Hay que añadir un atributo de ordenación explícito |
| Mover / renombrar | Reescribir todos los descendientes | Actualizar un puntero parent |
| Listado de hijos directos | Necesita atributo de profundidad o GSI | Natural (parent = x) |
Las claves compuestas ganan cuando las lecturas tienen forma de subárbol y la ordenación importa; el modelo de ID plano gana cuando el árbol muta constantemente. La mayoría de las jerarquías intensivas en lecturas — árboles de archivos, árboles de categorías, organigramas — se inclinan hacia las compuestas.
Trampas y próximos pasos
- No sobrecargues la clave. Todo lo que codificas es inmutable e indexado solo por prefijo. Los atributos por los que consultas por igualdad pertenecen a sus propios campos o a un GSI, no embutidos en la clave de ordenación.
- Una clave de ordenación no puede hacer un
WHEREarbitrario. Solobegins_with,betweeny comparaciones. Si te encuentras recurriendo a unFilterExpression, probablemente has modelado mal la clave — ver Query vs. Scan. - Profundizar en el diseño de claves vive en single-table design; para cuando una lectura de subárbol necesita un índice en lugar de la tabla base, ver GSI vs. LSI.
Construye la condición de clave begins_with con el
Expression Builder, luego
descarga DynoTable para ejecutar estas consultas de prefijo contra tus
propias tablas y ver volver un subárbol en orden de ruta.


