DynamoDB Strategie di filtraggio
"Filtrare" in DynamoDB significa quattro cose diverse che portano la stessa parola. Tre restringere i dati prima che vengano letti e fatturati; uno — quello denominato "Filtro" — lo restringe dopo. Sapere qual è la parte più importante dell'abilità.
Come funziona il filtraggio in DynamoDB?
DynamoDB ha quattro modi per filtrare e solo uno viene eseguito dopo l'addebito. ILseleziona una partizione, la chiave di ordinamento restringe una sezione e un indice sparso filtra in base alla presenza di attributi: tutti e tre riducono i costi di lettura prima della misurazione. Un FilterExpression viene eseguito dopo la lettura, quindi riduce la risposta ma mai il conto.
- è il filtro più economico: seleziona la partizione, quindi non lo farai mai
toccare il resto della tabella.
- filtra all'interno di una partizione con begins_with, between, <,
> — ancora prima della fatturazione, ancora economico.
-filtra per assenza: un elemento appare nell'indice solo se
ha l'attributo indicizzato, quindi l'indice è l'insieme filtrato.
FilterExpressionè la trappola: corre dopo DynamoDB metri dalla lettura, quindi riduce la dimensione della risposta ma mai la bolletta.
Imposta l'esempio
Un catalogo prodotti. Una tabella, chiave di partizione PK, chiave di ordinamento SK:
PK = "DEPT#kitchen" SK = "PROD#00194"
Ogni prodotto riporta anche "price", "inStock" (un valore booleano) e "clearanceAt". (un timestamp unix, presente solo sugli elementi contrassegnati per l'autorizzazione). Elementi in a il reparto condivide una partizione, ordinata per ID prodotto.
Vogliamo quattro modelli di accesso. Ognuno si associa a una diversa strategia di filtraggio:
e la scelta sbagliata su ognuno di essi è un Scan che pagherai per sempre.
Filtra per chiave di partizione
"Dammi ogni prodotto in cucina." La chiave di partizione risponde direttamente a questa domanda:
Query PK = "DEPT#kitchen"
DynamoDB legge esattamente una partizione. Nient'altro nella tabella viene toccato o
fatturato. Questo è l'unico filtro gratuito nel senso che conta: è il
differenza tra Query e Scan.
Venendo da SQL, questo sembra al contrario: non c'è WHERE dipartimento = 'cucina'
scansionando un indice, basta rinominare la partizione. Se non puoi dargli un nome, è a
problema di modellazione, non un problema di query.
Filtra per chiave di ordinamento
"Dammi i prodotti da cucina dal PROD#00100 in su." La chiave di ordinamento restringe dentro
la partizione, e lo fa prima che la lettura venga misurata:
Query PK = "DEPT#kitchen" AND SK between "PROD#00100" AND "PROD#00200"
Le condizioni della chiave di ordinamento sono appositamente limitate: =, <, <=, >, >=,
"tra" e "begins_with". Nessun "OR", nessun predicato arbitrario.
Questo vincolo è ciò che mantiene la lettura mirata: DynamoDB cammina in modo contiguo porzione, non l'intera partizione.
La leva qui è come codificare la chiave di ordinamento. Se il tuo modello è "per prezzo
band", una chiave di ordinamento PROD#<id> non aiuta: inseriresti il prezzo nella chiave.
Questa è una decisione di strategia di ordinamento, presa in fase di progettazione, non in fase di query.
Filtra per indice sparso
"Dammi tutto ciò che è attualmente in liquidazione." La maggior parte dei prodotti non lo sono, quindi non lo fai tu voglio leggere il catalogo per trovare i pochi che sono.
Un indice sparso risolve questo problema per assenza. UNsolo contiene un elemento se quell'elemento ha entrambi gli attributi chiave dell'indice.
Imposta un flag costante clearance = "CLEARANCE" come chiave di partizione GSI —
scritto solo su elementi da liquidare, con "clearanceAt" come chiave di ordinamento e il file
l'indice non contiene nient'altro.
AWS lo spiega chiaramente: un indice secondario globale contiene solo elementi che hanno l'estensione gli attributi chiave dell'indice, quindi gli elementi a cui manca l'attributo chiave semplicemente non lo sono propagato (AWS — Approfitta degli indici sparsi).
Ora la query legge solo gli articoli in liquidazione, fatturati solo per essi:
Query ON ClearanceIndex GSI_PK = "CLEARANCE" (sorted by clearanceAt)
Il filtro è stato attivato quando hai scritto i dati, scegliendo se impostarli "clearanceAt" affatto. L'indice è l'insieme filtrato. Vedi GSI vs LSI per quale tipo di indice si adatta.
Filtra con FilterExpression
"Dammi i prodotti da cucina che sono in stock." "inStock" non è un attributo chiave,
quindi raggiungi un FilterExpression:
Query PK = "DEPT#kitchen"
Filter inStock = true
DynamoDB legge ogni articolo nella partizione cucina, misura la capacità di
tutti e poi elimina quelli esauriti.
AWS afferma che un'espressione di filtro viene "applicata al termine di Query, ma
prima che i risultati vengano restituiti" e "a Query consuma la stessa quantità di lettura
capacità, indipendentemente dal fatto che sia presente un'espressione di filtro" — già
pagato per la lettura completa (AWS — Espressioni filtro per Query).
Quindi se "cucina" ha 10.000 prodotti e 12 sono in stock, paghi per leggerne 10.000. La risposta è piccola; il conto no. "FilterExpression" riduce il carico utile attraversando il filo, mai la lettura.
C'è un secondo aspetto più netto: l'impaginazione viene misurata prima del filtraggio. Una pagina corrisponde a 1 MB di elementi letti, non a 1 MB di corrispondenze.
Un filtro può restituire una pagina vuota con un set LastEvaluatedKey — DynamoDB leggi un
megabyte pieno, non corrispondeva a nulla, ti ha consegnato un array vuoto. Continui a cercare e
hai pagato per ogni pagina vuota.
Costruisci l'espressione (nomi, valori e l'escape della parola riservata corretta) con
il DynamoDB Expression Builder quindi il
I segnaposto #inStock/:val sono corretti al primo tentativo.
Il builder di seguito è preimpostato su Scan con FilterExpression — l'esatto
anti-modello sopra. Nota che il filtro viene eseguito sull'intera tabella, non su una porzione chiave:
Confronta i quattro
| Quando filtra | Taglia i costi di lettura? | Potere predicativo | Costo per l'installazione | |
|---|---|---|---|---|
| Chiave di partizione | Prima di leggere | Sì, una partizione | Solo uguaglianza | Libero (è la chiave) |
| Chiave di ordinamento | Prima di leggere | Sì, una fetta | Intervallo / begins_with | Design con chiave di ordinamento |
| Indice sparso | Prima di leggere | Sì: solo indice | Presenza di un attributo | Extra GSI + costo di scrittura |
| FilterExpression | Dopo aver letto | No | Quasi tutte le condizioni | Nessuno |
Leggi la tabella da cima a fondo: il potere dei predicati aumenta, il controllo dei costi diminuisce
giù. FilterExpression può esprimere qualsiasi cosa proprio perché continua
articoli già letti: è lo stesso motivo per cui non può farti risparmiare denaro.
Vedilo in DynoTable
Quando esegui un Query con un filtro, il divario tra gli elementi read e items
restituito è tutta la storia. DynoTable mostra gli elementi scansionati accanto agli elementi
restituito come flusso di lettura filtrato, quindi un filtro che legge silenziosamente l'intera partizione non è visibile
nascosti nella fattura mensile.
Per domande autentiche su più articoli a cui un filtro non può rispondere: "prezzo medio per
dipartimento", "prodotti in stock uniti alle loro recensioni" — DynoTable's SQL
Workbench esegue GROUP BY, JOIN e aggrega il lato client su un
set di risultati, invece di compilare in un Scan a livello di tabella.
Insidie e passaggi successivi
- Non utilizzare
FilterExpressioncome percorso di accesso principale. Se un modello lo è comune, modellalo in una chiave o in un indice sparso. Un filtro è per l'ultimo piccolo un po' di restringimento, non il grosso. - Guarda le pagine vuote. Una query filtrata può restituire pagine per molto tempo niente. Onore a "LastEvaluatedKey"; non dare per scontato che una pagina vuota significhi "fatto".
- Un indice sparso non è gratuito. Richiede capacità di scrittura e archiviazione per ogni oggetto che vi arriva: economico quando l'attributo è raro, meno quando non lo è.
Stima quanto costerà effettivamente una lettura filtrata con il calcolatore dei prezzi e prova DynoTable per controllare la capacità consumata rispetto alle righe restituite i tuoi tabelle