DynamoDB Espressioni di condizioni chiave
Un'espressione di condizione chiave è il KeyConditionExpression che passi a a
Query — l'unica parte della richiesta che DynamoDB utilizza per trovare elementi. Tutto
altrimenti (filtri, proiezioni) viene eseguito dopo che la lettura è già stata misurata.
Qual è l'espressione di una condizione chiave in DynamoDB?
Un'espressione di condizione chiave è KeyConditionExpression su un Query che indica a DynamoDB quali elementi leggere. ILdeve essere un'uguaglianza (PK = :v); ILaccetta un operatore di intervallo: =, <, <=, >, >=, BETWEEN o begins_with. Decide cosa viene letto e fatturato, a differenza di un filtro.
- ILdeve essere un'uguaglianza.
PK = :ve nient'altro — no intervalli, nientebegins_with, nienteIN. DynamoDB esegue l'hashing per individuare una partizione. - ILaccetta un operatore di intervallo.
=,<,<=,>,>=,BETWEEN, obegins_with— qui è dove dividi un. - Non è un filtro. Una condizione chiave decide cosa viene letto e fatturato; un
FilterExpressionritaglia il risultato solo dopo aver pagato per la lettura. - Le chiavi di ordinamento sono ordinate per byte. Gli operatori di intervallo si confrontano lessicograficamente, quindi il modo in cui formatti la stringa della chiave di ordinamento è la tua potenza di query.
Perché la chiave di partizione è bloccata sull'uguaglianza
DynamoDB memorizza gli elementi eseguendo l'hashing della chiave di partizione su una partizione fisica. A hash ti fornisce una posizione, non un intervallo, quindi non c'è nulla da scansionare attraverso.
Ecco perché PK > :v o begins_with(PK, :v) vengono rifiutati completamente. Il motore
non è possibile rispondere a "tutte le partizioni la cui chiave inizia con X" senza leggere l'intero
table, che è esattamente il Scan che è stato costruito per evitare.
Venendo da SQL, questo sembra al contrario: WHERE id LIKE 'order%' è banale in
Postgres. In DynamoDB la chiave di partizione è un indirizzo, non una colonna ricercabile.
La chiave di ordinamento è dove risiede il potere
All'interno di una partizione, gli elementi vengono archiviati ordinati in base alla chiave di ordinamento. Quell'ordinamento è ciò che sfruttano gli operatori di range: DynamoDB cerca una posizione e legge in avanti.
| Operatore | Legge | Usalo per |
|---|---|---|
SK = :v | Un articolo esatto | Un bambino specifico per la tua chiave |
SK < / <= / > / >= :v | Una fetta aperta | "Tutto dopo questo punto" |
SK TRA :aE :b | Un intervallo chiuso (compreso) | Una finestra delimitata: un intervallo di date |
begins_with(SK, :p) | Una fetta di prefisso | Un tipo o gerarchia sotto PK |
Non c'è nessun LIKE, nessun CONTAINS, nessun ENDS_WITH sulla chiave. Sottostringa e
la corrispondenza dei suffissi non è ordinata per byte, quindi forzerebbe una lettura completa: in base alla progettazione,
il API non te lo permetterà. La corrispondenza delle sottostringhe esiste tramite contains() in a
FilterExpression (dove hai già pagato per la lettura); corrispondenza del suffisso
non è affatto disponibile lato server: memorizza una chiave invertita o filtrala
lato client. (AWS: Espressioni delle condizioni chiave)
Un esempio funzionante: messaggi in un'app di chat
Supponiamo che tu stia creando una chat basata sul canale. Una tabella, partizionata per canale, ordinati per ora del messaggio. Schema chiave originale:
- Chiave di partizione
ChannelRef—CH#{channelId} - Chiave di ordinamento "PostedAt": un timestamp ISO-8601, "MSG#2026-06-23T14:05:00Z"
Il prefisso "MSG#" mantiene le righe dei messaggi ordinabili e distinte da qualsiasi altra riga tipo che potresti co-localizzare nello stesso canale (configurazione bloccata, appartenenza).
Carica gli ultimi messaggi di un canale. Solo la chiave di partizione, iniziando dal più recente:
KeyConditionExpression ChannelRef = :ch
ExpressionAttributeValues { ":ch": "CH#general" }
ScanIndexForward false
ScanIndexForward: false percorre la raccolta ordinata al contrario: il modo economico
per ottenere "prima il più recente" senza ordinare sul lato client.
Un giorno specifico con begins_with. Poiché il timestamp è la chiave di ordinamento e
è memorizzato come testo, un prefisso di data è una sezione pulita:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Questo legge ogni messaggio del 23-06-2026 e nient'altro: DynamoDB cerca il prefisso e si ferma quando cade alla fine. Funziona solo perché il prefisso è un vero ancoraggio sinistro di una stringa ordinata per byte.
Una finestra precisa con BETWEEN. Per "i messaggi durante le ore 14:00",
un intervallo inclusivo batte un prefisso:
KeyConditionExpression ChannelRef = :ch AND PostedAt BETWEEN :lo AND :hi
:ch "CH#general"
:lo "MSG#2026-06-23T14:00:00Z"
:hi "MSG#2026-06-23T14:59:59Z"
"BETWEEN" è inclusivo su entrambi i limiti, quindi scegli deliberatamente i tuoi endpoint: an off-by-one qui rilascia o raddoppia silenziosamente un messaggio edge.
Puoi assemblare e copiare qualsiasi di queste espressioni, con il file
Mappa ExpressionAttributeValues compilata per te, nel file
DynamoDB generatore di espressioni — utile per
ottenere la sintassi begins_with e BETWEEN corretta la prima volta.
Questo builder è preimpostato su una query pk = … AND begins_with(sk, …): modifica la
operatore per vedere l'aggiornamento KeyConditionExpression:
Vedilo in DynoTable
Esegui la stessa condizione chiave su una partizione del canale reale. Nel momento in cui trascorri
un filtro della chiave di partizione, DynoTable emette un Query — quindi carichi solo quella porzione,
non l'intera collezione.
La trappola: confondere una condizione chiave con un filtro
L'errore costoso è prendere FilterExpression per fare il lavoro di una chiave. A
il filtro non può nemmeno fare riferimento a PostedAt: è la chiave di ordinamento e DynamoDB rifiuta
un filtro su un attributo chiave con una ValidationException. Quindi la soluzione alternativa è quella di
duplica la data in un attributo semplice, non chiave (MessageDate) e filtra
che invece:
KeyConditionExpression ChannelRef = :ch
FilterExpression begins_with(MessageDate, :day)
Questo sembra equivalente alla condizione chiave begins_with sopra e restituisce il file
stesse righe, ma prima legge l'intera partizione del canale, quindi la scarta
tutto fuori dal giorno. Ti verrà addebitata la lettura completa.
I filtri non riducono mai i costi di lettura. Corrono dopo che DynamoDB ha misurato gli oggetti,
lo stesso fucile di un Scan filtrato. Se un predicato
può andare nella condizione chiave, appartiene a lì.
Risolvilo a monte. Se un modello di accesso non può essere espresso come un'uguaglianza PK più un intervallo di chiavi di ordinamento, questo è un segnale di modellazione. Rimodellare la chiave di ordinamento oppure aggiungi un indice con chiave per il modello - vedi GSI vs LSI e design a tabella singola per sapere come disporre le chiavi.
Insidie e passaggi successivi
- La chiave di partizione è sempre
=. Nessun intervallo, mai. Se hai bisogno di una gamma ampia partizioni, sei diventato troppo grande per un singoloQuery. - Una condizione della chiave di ordinamento per query. Non è possibile eseguire l'operazione "AND" tra due predicati della chiave di ordinamento;
scegli
BETWEENobegins_with, non entrambi. - Le parole riservate necessitano di alias. È necessario utilizzare una chiave denominata "Timestamp" o "Nome".
"ExpressionAttributeNames" (
#ts) o errori di query. (AWS: parole riservate) BETWEENè inclusivo. Entrambi gli endpoint sono abbinati: progetta i tuoi limiti di conseguenza.
Redigere le condizioni chiave nel file costruttore di espressioni, quindi prova DynoTable per confrontarli con i tuoi tabelle e vedere esattamente quale fetta restituisce ciascuna condizione chiave.