Liest der Shop jede Bestellung?
Ein Online-Shop hält eine Million Bestellungen. Eine Kundin will ihre eigenen sehen. Liest der Shop dafür alle Bestellungen durch?
Eine gut gebaute DynamoDB-Tabelle tut das nicht. Eine DynamoDB-Query geht direkt zu den Bestellungen der Kundin und liest sonst nichts. Diese Lektion zeigt, warum eine Query billiger ist als ein Scan, und wie Sie die Zahlen lesen, die der Dienst zurückgibt.
Am Ende dieser Lektion
Notiz
Ich kann erklären, warum eine Query billiger ist als ein Scan.
Schlüsselwörter
| Begriff | Was er bedeutet |
|---|---|
| Partitionsschlüssel | das Attribut, das bestimmt, wo ein Item gespeichert wird |
| Sortierschlüssel | das Attribut, das die Items innerhalb eines Partitionsschlüssels ordnet |
| Schlüsselbedingung | der Test, den eine Query auf die Schlüssel macht |
| Query | ein Lesezugriff, der zu einem Partitionsschlüssel geht |
| Scan | ein Lesezugriff, der jedes Item der Tabelle ansieht |
| Filter | ein Test, der erst nach dem Lesen der Items angewendet wird |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Zwei Schlüssel geben jedem Item eine Adresse
Unsere Bestelltabelle hat zwei Schlüsselattribute. Der Partitionsschlüssel ist kunde. Er bestimmt, wo der Dienst ein Item ablegt, sodass alle Bestellungen einer Kundin zusammenliegen.
Der Sortierschlüssel ist bestell_id. Er ordnet die Bestellungen einer Kundin. Beide Schlüssel zusammen nennen genau ein Item. Zwei Bestellungen dürfen denselben Kunden haben, aber nie beide Schlüssel.
Beispiel: wie die Bestellungen liegen
| Partitionsschlüssel: kunde | Sortierschlüssel: bestell_id | Weitere Attribute |
|---|---|---|
| lena | 1 | Tee, bezahlt, Summe 4 |
| lena | 2 | Milch, neu, Summe 2 |
| lena | 3 | Kuchen, bezahlt, Summe 15 |
| tobias | 7 | Tee, bezahlt, Summe 8 |
| yusuf | 4 | Milch, neu, Summe 6 |
| yusuf | 9 | Tee, bezahlt, Summe 3 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Query geht an einen Ort, Scan überallhin
Eine Query nennt den Partitionsschlüssel. Sie muss es, sonst lehnt der Dienst sie mit einer ValidationException und dem HTTP-Status 400 ab. Der Dienst geht direkt zu dieser Kundin und liest nur ihre Bestellungen.
Ein Scan nennt nichts. Er liest jedes Item der Tabelle, eins nach dem anderen. Beide Antworten tragen ein Count, die zurückgegebenen Items, und ein ScannedCount, die angesehenen Items.
Run: eine Query und ein Scan
bestellungen = [
{"kunde": {"S": "lena"}, "bestell_id": {"N": "1"}, "status": {"S": "bezahlt"}},
{"kunde": {"S": "lena"}, "bestell_id": {"N": "2"}, "status": {"S": "neu"}},
{"kunde": {"S": "lena"}, "bestell_id": {"N": "3"}, "status": {"S": "bezahlt"}},
{"kunde": {"S": "tobias"}, "bestell_id": {"N": "7"}, "status": {"S": "bezahlt"}},
{"kunde": {"S": "yusuf"}, "bestell_id": {"N": "4"}, "status": {"S": "neu"}},
{"kunde": {"S": "yusuf"}, "bestell_id": {"N": "9"}, "status": {"S": "bezahlt"}},
]
def scan(items):
return {"Count": len(items), "ScannedCount": len(items)}
def query(items, kunde):
gefunden = []
for item in items:
if item["kunde"]["S"] == kunde:
gefunden.append(item)
return {"Count": len(gefunden), "ScannedCount": len(gefunden)}
print("Scan:", scan(bestellungen))
print("Query lena:", query(bestellungen, "lena"))
# Ändern Sie "lena" in "tobias". Wie viele Items sieht die Query jetzt an?
Ein Filter kürzt die Antwort, nicht die Arbeit
Eine Schlüsselbedingung darf auch den Sortierschlüssel prüfen, zum Beispiel bestell_id ab 2. Dann liest der Dienst nur diesen Teil der Partition.
Ein Filter prüft jedes andere Attribut, etwa status. Er läuft erst nach dem Lesen der Items, ändert also den Count, aber nicht den ScannedCount.
Beispiel: Lenas bezahlte Bestellungen ab 2
| Schritt | Items übrig | Was geschah |
|---|---|---|
| Partitionsschlüssel ist lena | 3 | Bestellungen 1, 2 und 3 |
| Sortierschlüssel ab 2 | 2 | Bestellungen 2 und 3, also ScannedCount 2 |
| Filter: status ist bezahlt | 1 | nur Bestellung 3, also Count 1 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele denken, ein Filter mache das Lesen billiger. Das stimmt nicht. Der Dienst liest die Items zuerst und wirft danach einige weg. Legen Sie alles, was geht, in die Schlüsselbedingung und nehmen Sie den Filter nur für den Rest.
Run: die beiden Zahlen lesen
antwort = {
"Count": 1,
"ScannedCount": 2,
"Items": [
{"kunde": {"S": "lena"}, "bestell_id": {"N": "3"}, "status": {"S": "bezahlt"}},
],
}
verworfen = antwort["ScannedCount"] - antwort["Count"]
print("angesehen:", antwort["ScannedCount"])
print("zurückgegeben:", antwort["Count"])
print("vom Filter verworfen:", verworfen)
# Ändern Sie ScannedCount in 3. Wie viele hat der Filter jetzt verworfen?