Intermedio6 min de lectura

Claves de ordenación compuestas en DynamoDB

Una es una clave de partición más una clave de ordenación. El truco que la hace potente es lo que pones dentro de la sort key: codifica una jerarquía como una sola cadena delimitada, y un solo Query lee un subárbol entero en orden de sort — sin joins, sin recursión, sin un segundo round-trip.

¿Cómo funcionan las claves de ordenación compuestas en DynamoDB?

Una sort key compuesta empaqueta una jerarquía en una sola cadena delimitada — root/photos/2026/ — que DynamoDB guarda en orden de bytes UTF-8. Como el layout ya coincide con el árbol, un solo Query con begins_with(SK, "root/photos/") lee un subárbol entero en orden de path. Sin joins, sin recursión, sin un segundo round-trip — solo un scan de prefijo sobre un contiguo.

  • La sort key es una cadena ordenable, no solo un ID. Empaqueta un path en ella — root/photos/2026/ — y DynamoDB guarda los items de la partición en orden de bytes UTF-8 automáticamente.
  • Un delimitador convierte los matches de prefijo en lecturas de subárbol. begins_with(SK, "root/photos/") devuelve cada descendiente de esa carpeta en una sola query.
  • Las sort keys 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 un Scan.
  • El delimitador carga peso. Elige uno que no pueda aparecer en un segmento de path, o dos ramas no relacionadas chocan.

Por qué la sort key es todo el juego

Si vienes de SQL, modelarías un árbol de carpetas con un self-join de parent_id y lo recorrerías en recursión — una query por nivel. En DynamoDB eso es un pie N+1 contra un almacén clave-valor que no tiene joins.

DynamoDB guarda cada item bajo una clave de partición ordenado por su sort key, en orden de bytes UTF-8 para strings (AWS: Query key conditions). Así que si tu sort key es el path, el layout físico ya coincide con el árbol. Una lectura se convierte en un scan de prefijo sobre un trozo contiguo — no en un paseo por un grafo.

Ese es el cambio: la sort key no es un identificador que matcheas exactamente. Es una dirección ordenable. Diseñala y la query sale gratis.

Modela un árbol de sistema de ficheros

Digamos que guardas árboles de ficheros por cuenta. Un drive por cuenta es la partición natural; el path dentro es la sort key.

PKSKnode_typebytes
DRIVE#a91root/folder-
DRIVE#a91root/docs/folder-
DRIVE#a91root/docs/taxes.pdffile88210
DRIVE#a91root/photos/folder-
DRIVE#a91root/photos/2026/folder-
DRIVE#a91root/photos/2026/beach.jpgfile284910
DRIVE#a91root/photos/2026/sunset.jpgfile512004

Dos convenciones originales haciendo el trabajo aquí:

  • PK = DRIVE#<account> mantiene el árbol entero de una cuenta en una sola , así que cualquier lectura de subárbol es un Query de una sola partición.
  • SK es el path completo con una / final en las carpetas. La barra final es deliberada — hace que una carpeta ordene antes que sus propios hijos y mantiene root/photos/ distinto de un fichero hermano llamado root/photos.

Lee un subárbol en una sola query

Lista todo bajo root/photos/ — carpeta, subcarpetas y ficheros, en recursión:

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 path, en una sola lectura facturada. Solo pagas por los items de ese trozo, no por el drive entero.

En DynoTable lanzas exactamente este Query con begins_with contra la sort key de path y la carpeta más sus descendientes vuelven en orden de path — sin sintaxis de placeholder que escribir a mano.

¿Necesitas el KeyConditionExpression crudo (nombres, valores y begins_with) para tu propio código? Constrúyelo y cópialo en el generador de expresiones de DynamoDB.

Ejecutando un Query con begins_with sobre la sort key de path en DynoTable, que devuelve una carpeta y sus descendientes en orden de path.
Ejecutando un Query con begins_with sobre la sort key de path en DynoTable, que devuelve una carpeta y sus descendientes en orden de path.

Lista un nivel, no el subárbol entero

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 — guarda un atributo depth y añade un rango de sort key más un filtro, o parte el path en un GSI de parent. La versión más simple: mantén un atributo parent (root/photos/) y un GSI claveado sobre él.

Una sort key responde barato a preguntas de prefijo y rango. «Solo hijos directos» es otra pregunta — modélala explícitamente en lugar de esperar que un FilterExpression la haga eficiente. Un filtro corre después de la lectura y pagas por cada item que descarta.

Elige el delimitador con cuidado

El delimitador es parte de tu contrato de datos. Dos reglas:

  • Nunca debe aparecer dentro de un segmento de path. Si los nombres de fichero pueden contener /, / es el delimitador equivocado — un fichero llamado a/b es indistinguible de una carpeta a que contiene b. Elige un byte reservado (algunos equipos usan # o un carácter de control) y prohíbelo en los segmentos.
  • Cuida el orden de sort en los límites. / (0x2F) ordena antes que dígitos y letras, que suele ser lo que quieres para orden de árbol. Cambia el delimitador y cambias el ordenamiento — verifícalo contra datos reales.

Sort key compuesta vs. un atributo de sort aparte

Sort key compuesta (root/photos/2026/x)Sort key ID plano + atributo parent
Lectura de subárbolUn Query con begins_withQueries recursivas (N+1) o un paseo por GSI
OrdenamientoOrden de path, gratisHay que añadir un atributo de sort explícito
Move / renameReescribir todos los descendientesActualizar un puntero parent
Lista de hijos directosNecesita attr depth o GSINatural (parent = x)

Las claves compuestas ganan cuando las lecturas son en forma de subárbol y el orden importa; el modelo de ID plano gana cuando el árbol muta sin parar. La mayoría de jerarquías read-heavy — árboles de ficheros, de categorías, org charts — se inclinan por la compuesta.

Escollos y próximos pasos

  • No sobrecargues la clave. Todo lo que codificas es inmutable e indexado solo por prefijo. Los atributos que consultas por igualdad van en sus propios campos o en un GSI, no metidos a presión en la sort key.
  • Una sort key no hace WHERE arbitrarios. Solo begins_with, between y comparaciones. Si te pillas buscando un FilterExpression, probablemente modelaste la clave mal — ver Query vs. Scan.
  • Ir más a fondo en el diseño de claves vive en el 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 key condition con begins_with en el Expression Builder, luego descarga DynoTable para lanzar estos Queries de prefijo contra tus propias tablas y ver un subárbol volver en orden de path. (¿Y el self-JOIN que dejaste atrás en SQL? El SQL Workbench de DynoTable sigue ejecutándolo cuando lo necesitas.)

Actualizado

Prueba este diseño de forma interactiva

Esboza tus entidades y patrones de acceso en la herramienta gratuita de diseño de tabla única de DynamoDB: sugiere plantillas de claves PK/SK, previsualiza las colecciones de Items y muestra qué patrones necesitan un GSI.

Abrir la herramienta de diseño de tabla única