Einsteiger5 Min. Lesezeit

DynamoDB-Projection-Expressions

Eine Projection Expression ist das SELECT col1, col2 von DynamoDB: eine kommaseparierte Liste von namen, die GetItem, Query oder Scan sagt, nur diese Attribute statt des ganzen Items zurückzugeben.

Reduzieren DynamoDB-Projection-Expressions Read-Kosten?

Nein. Eine ProjectionExpression trimmt das Response-Payload, nicht die Read Capacity, die abgerechnet wird. DynamoDB liest das volle Item aus Storage, metert die anhand seiner On-Disk-Größe und droppt dann die Attribute, die du nicht genannt hast, auf dem Weg raus. Um Read-Kosten wirklich zu senken, nutze stattdessen einen covering .

  • Sie trimmt das Payload, nicht die Read-Kosten. DynamoDB liest (und rechnet) das volle Item aus Storage und droppt dann die Attribute, die du nicht genannt hast, auf dem Weg raus. ProjectionExpression ist eine Network-Optimierung, keine Capacity-eine.
  • So holst du eine public Subset. Nenne die wenigen Attribute, die ein Caller sehen darf; der Rest verlässt die Tabelle nie.
  • Nutze #name-Placeholder für alles, was reserved sein könnte. Plaine Attributnamen in der Expression kollidieren mit DynamoDBs ~570 Reserved Words und failen den Request.
  • Für echte Read-Ersparnis nutze stattdessen einen Covering Index. Ein , der nur die Columns projeziert, die du brauchst, wird bei seiner eigenen (kleineren) Größe gelesen.

Was sie wirklich spart

Aus SQL würdest du annehmen, SELECT a, b scannt weniger als SELECT *. In DynamoDB ist diese Intuition falsch. Die Capacity Unit für einen Read wird aus der Größe des Items on Disk berechnet, aufgerundet auf die nächsten 4 KB — bevor die Projektion angewandt wird. AWS ist explizit: eine ProjectionExpression ändert nicht die Read Capacity, die ein Request verbraucht.1

Eine Projektion spart dir also zwei Dinge, beide real, aber beide downstream des Reads:

  • Bytes über die Leitung. Ein 6-KB-Item, zurückgegeben als zwei kleine Attribute, ist eine winzige Response. Auf einer Query, die Hunderte Items zurückgibt, summiert sich das schnell.
  • Clientseitige Arbeit. Weniger zu deserialisieren, weniger im Memory zu halten, weniger versehentlich in ein Log oder eine API-Response zu leaken.

Was sie nicht spart, ist die RCU. Das ist der Fallstrick: Leute greifen nach einer Projektion, um die Rechnung zu senken, sehen keine Änderung und schließen, DynamoDB sei broken. Ist es nicht — du hast den falschen Hebel gemessen.

Ein öffentliches User-Profil projeizieren

Angenommen, du betreibst ein User Directory. Jedes Profil ist ein Item, so gekeyed, dass du eine Person per Handle fetchen kannst:

PK = "PROFILE#ada"      (partition key)
SK = "PROFILE#ada"      (sort key — single-item collection)

Das Item ist fett. Es trägt das öffentliche Gesicht des Accounts plus einen Haufen privater und operationaler Attribute:

{
  "PK": "PROFILE#ada",
  "SK": "PROFILE#ada",
  "displayName": "Ada L.",
  "avatarUrl": "https://cdn.example.com/u/ada.png",
  "bio": "Builds things.",
  "emailAddress": "ada@example.com",
  "passwordResetToken": "…",
  "billingCustomerId": "cus_…",
  "lastLoginIp": "…",
  "internalRiskScore": 0.02
}

Eine öffentliche Profilkarte braucht drei Felder. Das ganze Item zu fetchen heißt, emailAddress, lastLoginIp und internalRiskScore reisen in einen Kontext, der sie nie sehen sollte. Nenne nur die public Subset:

GetItem  PK = "PROFILE#ada"  SK = "PROFILE#ada"
ProjectionExpression: displayName, avatarUrl, bio

Die Response trägt drei Attribute. Die privaten bleiben in der Tabelle — nicht von deiner App nach Ankunft herausgefiltert, sondern nie überhaupt in die Response serialisiert. Das ist der Security-Win, und er ist schwer rückgängig zu machen, sobald ein Secret eine Boundary gekreuzt hat.

Du kannst genau diesen Request — Names, Placeholder und den SDK-Call — im DynamoDB Expression Builder zusammenbauen und kopieren, der die ProjectionExpression und ExpressionAttributeNames-Map für dich emittiert.

Füge Felder im Preset unten hinzu oder entferne sie, um die ProjectionExpression zu beobachten — nur die gelisteten Attribute kommen zurück:

Erstelle deine Anfrage
Generierter Code
new QueryCommand({
  "TableName": "AuditLog",
  "KeyConditionExpression": "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)",
  "ProjectionExpression": "#proj0, #proj1, #proj2",
  "ExpressionAttributeNames": {
    "#hashKey": "pk",
    "#rangeKey": "sk",
    "#proj0": "action",
    "#proj1": "actor",
    "#proj2": "createdAt"
  },
  "ExpressionAttributeValues": {
    ":hashKeyValue": {
      "S": "TENANT#acme"
    },
    ":rangeKeyValue": {
      "S": "EVENT#"
    }
  }
})

Reserved Words mit #-Placeholdern escapen

Eine saubere Projektion explodiert an Reserved Words. DynamoDB reserviert eine lange Liste — name, status, comment, size, timestamp und Hunderte mehr.2 Ist ein Attribut, das du projezierst, eines davon, wird der rohe Name in der Expression rejected.

Angenommen, das Profil hat auch ein status-Attribut ("active", "suspended"). Das failt:

ProjectionExpression   displayName, status

status ist reserved. Der Fix ist ein Expression Attribute Name — ein #- prefixed Placeholder, gemappt auf den echten Namen:

ProjectionExpression       displayName, #s
ExpressionAttributeNames   { "#s": "status" }

Derselbe Mechanismus greift in nested Attribute. Um ein einzelnes Feld aus einer Map oder ein Element einer List zu ziehen, nutze Document-Path-Syntax — und placeholder jedes Segment, denn jedes könnte reserved sein:

ProjectionExpression       #addr.#city, tags[0]
ExpressionAttributeNames   { "#addr": "address", "#city": "city" }

Eine praktische Regel: placeholder alles. Du musst nie merken, auf welchem der ~570 Reserved Words du stehst, und die Expression liest sich so oder so gleich. Und wenn du lieber wissen willst, welche Namen wirklich das Problem sind, paste sie in den Reserved-Words Checker — er flaggt die Kollisionen und emittiert die ExpressionAttributeNames-Alias-Map.

Wann ein Covering Index eine Projektion schlägt

Brauchst du wirklich, Read-Kosten zu senken — nicht nur Payload — ist der Hebel ein Global Secondary Index, der nur die Attribute projeziert, die du liest. Ein GSI ist eine separate Kopie der Daten; du wählst KEYS_ONLY, INCLUDE oder ALL für seine Projektion.3 Ein KEYS_ONLY- oder enger INCLUDE-Index ist physisch kleiner pro Item, also wird eine Query dagegen bei dieser kleineren Größe gemetered.

Das ist ein Covering Index: die Query wird vollständig aus dem Index beantwortet, kein Trip zurück zur Base Table. Nutze ihn, wenn ein hot Read Pattern nur je ein paar Attribute aus großen Items braucht.

ProjectionExpressionCovering GSI
Kürzt PayloadJaJa
Kürzt Read-KostenNeinJa — Read bei der Größe des Index
Extra StorageKeinerEine zweite Kopie der projezierten Felder
Extra Write-KostenKeineWrites propagieren zum Index
Am besten fürPrivate Felder verstecken; kleine WinsHot Reads weniger Felder aus großen Items

Der Index kostet dich Storage und Write Capacity, um Read Capacity zu sparen. Wert für einen häufigen Read eines dünnen Slice aus einem schweren Item; nicht wert, um ein One-off-GetItem zu shaven. Siehe GSI vs LSI für den Index-Typ, und wann ein GSI-Read stale sein kann, bevor du einen auf den Hot Path legst.

Fallstricke und nächste Schritte

  • Erwarte keine kleinere Rechnung. Eine Projektion allein ändert nie RCU. Wenn die Zahl sich nicht bewegt hat, ist das dokumentiertes Verhalten, kein Bug.
  • Placeholder Reserved Words. Ein nacktes name oder status in der Expression failt den Request — #-mappe es.
  • Schließe immer die Key-Attribute ein — sie addieren vernachlässigbares Payload und lassen dich das Item pagen oder re-fetchen.
  • Greif zu einem Covering Index nur, wenn ein hot Pattern wenige Felder aus großen Items liest; wäge zuerst Write-/Storage-Kosten.

Baue die ProjectionExpression und ihre Attribute-Name-Map im Expression Builder, und probier DynoTable, um diese Projektionen gegen deine eigenen Tabellen zu fahren und die Response schrumpfen zu sehen.


  1. AWS DynamoDB Developer Guide, Using projection expressions in DynamoDB — die Read Capacity richtet sich nach der Item-Größe, bevor irgendeine ProjectionExpression angewendet wird. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
  2. AWS DynamoDB Developer Guide, Reserved Words in DynamoDB. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
  3. AWS DynamoDB Developer Guide, Attribute Projections (KEYS_ONLY / INCLUDE / ALL). https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html

Aktualisiert