Composite Sort Key in DynamoDB
Una composite primary key è una chiave di partizione più una sort key. Il trucco che
la rende potente è ciò che metti dentro la sort key: codifica una gerarchia come un'unica
stringa delimitata, e una sola Query legge un intero sottoalbero in ordine di sort — niente
join, niente ricorsione, nessun secondo round-trip.
Come funzionano le composite sort key in DynamoDB?
Una composite sort key impacchetta una gerarchia in un'unica stringa delimitata — root/photos/2026/ — che DynamoDB memorizza in ordine di byte UTF-8. Poiché il layout corrisponde già all'albero, una sola Query con begins_with(SK, "root/photos/") legge un intero sottoalbero in ordine di percorso. Niente join, niente ricorsione, nessun secondo round-trip — solo una scansione per prefisso su una fetta contigua.
- La sort key è una stringa ordinabile, non solo un ID. Impacchettaci dentro un percorso —
root/photos/2026/— e DynamoDB memorizza gli Item della partizione in ordine di byte UTF-8 automaticamente. - Un delimitatore trasforma i match per prefisso in letture di sottoalbero.
begins_with(SK, "root/photos/")restituisce ogni discendente di quella cartella in una sola query. - Le sort key supportano condizioni di range, non filtri arbitrari. Hai
begins_with,between,>,<— progetta la chiave così che la lettura che ti serve sia un prefisso o un range, non unoScan. - Il delimitatore è portante. Scegline uno che non possa comparire in un segmento di percorso, altrimenti due rami non correlati collidono.
Perché la sort key è tutto il gioco
Venendo da SQL, modelleresti un albero di cartelle con un self-join su parent_id e lo
percorreresti ricorsivamente — una query per livello. In DynamoDB quello è un footgun N+1 contro
uno store chiave-valore che non ha join.
DynamoDB memorizza ogni Item sotto una chiave di partizione ordinato per la sua sort key, in ordine di byte UTF-8 per le stringhe (AWS: Query key conditions). Quindi se la tua sort key è il percorso, il layout fisico corrisponde già all'albero. Una lettura diventa una scansione per prefisso su una fetta contigua — non una camminata su grafo.
Questo è il cambio: la sort key non è un identificatore che abbini esattamente. È un indirizzo ordinabile. Progettala e la query ne deriva gratis.
Modella un albero di file system
Diciamo che stai memorizzando alberi di file per account. Un drive per account è la partizione naturale; il percorso al suo interno è la sort key.
| 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 |
Due convenzioni originali fanno il lavoro qui:
PK = DRIVE#<account>tiene l'intero albero di un account in un'unica item collection, così ogni lettura di sottoalbero è unaQuerysu singola partizione.SKè il percorso completo con uno/finale sulle cartelle. Lo slash finale è deliberato — fa ordinare una cartella prima dei propri figli e tieneroot/photos/distinto da un file fratello chiamatoroot/photos.
Leggi un sottoalbero in una sola query
Elenca tutto sotto root/photos/ — cartella, sottocartelle e file, ricorsivamente:
Query
KeyConditionExpression = PK = :drive AND begins_with(SK, :prefix)
:drive = "DRIVE#a91"
:prefix = "root/photos/"
Questo restituisce root/photos/, root/photos/2026/, beach.jpg e sunset.jpg —
in ordine di percorso, in una sola lettura fatturata. Paghi solo per gli Item in quella fetta, non
per l'intero drive.
In DynoTable, esegui esattamente questa query begins_with sulla sort key di percorso e
la cartella insieme ai suoi discendenti torna in ordine di percorso — senza dover scrivere
a mano la sintassi dei placeholder.
Hai bisogno del KeyConditionExpression grezzo (nomi, valori e begins_with) per il
tuo codice? Costruiscilo e copialo nel
DynamoDB Expression Builder.

Elenca un livello, non l'intero sottoalbero
begins_with ti dà la lettura ricorsiva. Per un listing di directory non ricorsivo —
i figli immediati di root/photos/ e niente di più profondo — memorizza un attributo
depth e aggiungi un range sulla sort key più un filtro, oppure dividi il percorso in
un GSI parent. La versione più semplice: tieni un attributo parent (root/photos/)
e un GSI con chiave su di esso.
Il punto: una sort key risponde a domande di prefisso e range a basso costo. "Solo i figli
diretti" è una domanda diversa — modellala esplicitamente invece di sperare che una
FilterExpression la renda efficiente. Un filtro gira dopo la lettura e paghi
per ogni Item che scarta.
Scegli il delimitatore con cura
Il delimitatore è parte del tuo contratto dati. Due regole:
- Non deve mai comparire dentro un segmento di percorso. Se i nomi di file possono contenere
/,/è il delimitatore sbagliato — un file chiamatoa/bè indistinguibile da una cartellaache contieneb. Scegli un byte riservato (alcuni team usano#o un control char) e vietalo nei segmenti. - Attenzione all'ordine di sort ai confini.
/(0x2F) si ordina prima di cifre e lettere, che di solito è ciò che vuoi per l'ordine dell'albero. Cambia il delimitatore e cambi l'ordinamento — verificalo su dati reali.
Composite sort key vs. attributo di sort separato
Composite sort key (root/photos/2026/x) | Sort key con ID semplice + attributo parent | |
|---|---|---|
| Lettura sottoalbero | Una query begins_with | Query ricorsive (N+1) o camminata su GSI |
| Ordinamento | Ordine di percorso, gratis | Devi aggiungere un attributo di sort esplicito |
| Spostamento / rinomina | Riscrivi tutti i discendenti | Aggiorna un puntatore parent |
| Elenco figli diretti | Serve attributo depth o GSI | Naturale (parent = x) |
Le composite key vincono quando le letture hanno forma a sottoalbero e l'ordinamento conta; il modello a ID piatto vince quando l'albero muta di continuo. La maggior parte delle gerarchie a prevalenza letture — alberi di file, alberi di categorie, organigrammi — pende verso le composite.
Errori e prossimi passi
- Non sovraccaricare la chiave. Tutto ciò che codifichi è immutabile e indicizzato per solo prefisso. Gli attributi che interroghi per uguaglianza appartengono ai loro campi o a un GSI, non incastrati nella sort key.
- Una sort key non può fare un
WHEREarbitrario. Solobegins_with,betweene confronti. Se ti ritrovi a reggiungere unaFilterExpression, probabilmente hai modellato la chiave male — vedi Query vs. Scan. - L'approfondimento sul design delle chiavi sta in single-table design; per quando una lettura di sottoalbero ha bisogno di un indice invece della tabella base, vedi GSI vs. LSI.
Costruisci la key condition begins_with con l'
Expression Builder, poi
scarica DynoTable per eseguire queste query per prefisso sulle tue
tabelle e osservare un sottoalbero tornare in ordine di percorso.


