Intermedio6 min di lettura

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 = :v e nient'altro — no intervalli, niente begins_with, niente IN. DynamoDB esegue l'hashing per individuare una partizione.
  • ILaccetta un operatore di intervallo. =, <, <=, >, >=, BETWEEN, o begins_with — qui è dove dividi un.
  • Non è un filtro. Una condizione chiave decide cosa viene letto e fatturato; un FilterExpression ritaglia 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.

OperatoreLeggeUsalo per
SK = :vUn articolo esattoUn bambino specifico per la tua chiave
SK < / <= / > / >= :vUna fetta aperta"Tutto dopo questo punto"
SK TRA :aE :bUn intervallo chiuso (compreso)Una finestra delimitata: un intervallo di date
begins_with(SK, :p)Una fetta di prefissoUn 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 ChannelRefCH#{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:

Costruisci la tua richiesta
Codice generato
new QueryCommand({
  "TableName": "AuditLog",
  "KeyConditionExpression": "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)",
  "ExpressionAttributeNames": {
    "#hashKey": "pk",
    "#rangeKey": "sk"
  },
  "ExpressionAttributeValues": {
    ":hashKeyValue": {
      "S": "TENANT#acme"
    },
    ":rangeKeyValue": {
      "S": "EVENT#2026-06"
    }
  }
})

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 singolo Query.
  • Una condizione della chiave di ordinamento per query. Non è possibile eseguire l'operazione "AND" tra due predicati della chiave di ordinamento; scegli BETWEEN o begins_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.

Aggiornato