Iniciante6 min de leitura

DynamoDB Expressões de projeção

Uma expressão de projeção é SELECT col1, col2 de DynamoDB: a lista separada por vírgula denomes que informam GetItem, Query ou Scan para retornar apenas esses atributos em vez do item inteiro.

As expressões de projeção DynamoDB reduzem o custo de leitura?

Não. Um ProjectionExpression reduz a carga útil da resposta, não a capacidade de leitura cobrada. DynamoDB lê o item completo do armazenamento, mede ode acordo com o tamanho do disco e, em seguida, elimina os atributos que você não nomeou ao sair. Para realmente reduzir o custo de leitura, use uma coberturaem vez de.

  • Ele reduz a carga útil, não o custo de leitura. DynamoDB lê (e fatura) o item completo do armazenamento e descarta os atributos que você não nomeou no caminho fora. ProjectionExpression é uma otimização de rede, não de capacidade.
  • É como você busca um subconjunto público. Nomeie os poucos atributos que um chamador possui permitido ver; o resto nunca sai da mesa.
  • Use espaços reservados #name para qualquer coisa que possa ser reservada. Simples nomes de atributos na expressão colidem com ~570 palavras reservadas de DynamoDB e falhar na solicitação.
  • Para economia real de leitura, use um índice de cobertura. Aque projeta apenas as colunas necessárias são lidas em seu próprio tamanho (menor).

O que realmente salva

Vindo de SQL, você assumiria que SELECT a, b varre menos que SELECT *. Em DynamoDB que a intuição está errada. O unidade de capacidade para uma leitura é calculada a partir de o tamanho do item no disco, arredondado para os próximos 4 KB — antes do projeção é aplicada. AWS é explícito: um ProjectionExpression não muda a capacidade de leitura que uma solicitação consome.1

Portanto, uma projeção economiza duas coisas, ambas reais, mas ambas a jusante da leitura:

  • Bytes over the wire. Um item de 6 KB retornado como dois atributos pequenos é um valor minúsculo resposta. Em um Query que retorna centenas de itens, isso aumenta rapidamente.
  • Trabalho do lado do cliente. Menos para desserializar, menos para manter na memória, menos para vazar em um log ou uma resposta API por acidente.

O que ele não salva é o RCU. Essa é a arma: as pessoas buscam uma projeção para cortar sua conta, não ver nenhuma mudança e concluir que DynamoDB está quebrado. Isso não é - você mediu a alavanca errada.

Projete um perfil de usuário público

Digamos que você execute um diretório de usuários. Cada perfil é um item, codificado para que você possa buscar um pessoa por identificador:

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

O item é gordo. Ele carrega a face pública da conta mais uma pilha de atributos privados e operacionais:

{
  "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
}

Um cartão de perfil público precisa de três campos. Buscar o item inteiro significa emailAddress, lastLoginIp e internalRiskScore viajam para um contexto que nunca deveria vê-los. Nomeie apenas o subconjunto público:

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

A resposta carrega três atributos. Os privados ficam na mesa — não filtrado pelo seu aplicativo após a chegada, mas nunca serializado na resposta de jeito nenhum. Essa é a vitória da segurança, e é aquela que é difícil de desfazer uma vez por segredo já ultrapassou uma fronteira.

Você pode montar e copiar esta solicitação exata – nomes, espaços reservados e o SDK chamada - no DynamoDB Expression Builder, que emite o mapa ProjectionExpression e ExpressionAttributeNames para você.

Adicione ou remova campos na predefinição abaixo para assistir ao ProjectionExpression change — apenas os atributos listados voltam:

Monte sua requisição
Código gerado
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#"
    }
  }
})

Escape de palavras reservadas com espaços reservados #

Uma projeção limpa explode em palavras reservadas. DynamoDB reserva uma longa lista de palavras — name, status, comment, size, timestamp e centenas de outras.[^reserved] Se um atributo que você está projetando for um deles, o nome bruto na expressão é rejeitado.

Suponha que o perfil também tenha um atributo status ("ativo", "suspenso"). Isso falha:

ProjectionExpression   displayName, status

status é reservado. A correção é um nome de atributo de expressão — um prefixo # espaço reservado mapeado para o nome real:

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

O mesmo mecanismo atinge atributos aninhados. Para extrair um único campo de um mapa, ou um elemento de uma lista, use a sintaxe do caminho do documento - e o espaço reservado para cada segmento, já que qualquer um deles poderia ser reservado:

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

Uma regra prática: espaço reservado para tudo. Você nunca precisa lembrar qual dos ~ 570 palavras reservadas em que você está, e a expressão é a mesma caminho. E se você preferir saber quais nomes são realmente o problema, cole-os no verificador de palavras reservadas - ele sinaliza as colisões e emite o mapa de alias ExpressionAttributeNames.

Quando um índice de cobertura supera uma projeção

Se você realmente precisa reduzir o custo de leitura - e não apenas a carga útil - a alavanca é uma Índice Secundário Global que projeta apenas os atributos que você lê. Um GSI é um cópia separada dos dados; você escolhe KEYS_ONLY, INCLUDE ou ALL para seu projeção.3 Um índice KEYS_ONLY ou INCLUDE estreito é fisicamente menor por item, então um Query contra ele é medido nesse tamanho menor.

Esse é um índice de cobertura: a consulta é respondida inteiramente a partir do índice, não viagem de volta para a mesa base. Use-o quando um padrão de leitura a quente precisar apenas de alguns atributos de itens grandes.

ProjectionExpressionCobertura GSI
Reduz a carga útilSimSim
Reduz custos de leituraNãoSim — leia no tamanho do índice
Armazenamento extraNenhumUma segunda cópia dos campos projetados
Custo extra de gravaçãoNenhumAs gravações são propagadas para o índice
Melhor paraOcultando campos privados; pequenas vitóriasLeituras interessantes de alguns campos de itens grandes

O índice custa armazenamento e capacidade de gravação para economizar capacidade de leitura. Vale a pena ler frequentemente uma fatia fina de um item pesado; não vale a pena raspar um GetItem único. Veja GSI vs LSI para escolher o tipo de índice e quando uma leitura GSI pode ficar obsoleta antes você coloca um no caminho quente.

Armadilhas e próximos passos

  • Não espere uma conta menor. Uma projeção por si só nunca muda RCU. Se o o número não se moveu, esse é o comportamento documentado, não um bug.
  • Palavras reservadas de espaço reservado. Um nome ou status simples na expressão falha na solicitação - #-mapeie-a.
  • Sempre inclua os principais atributos — eles adicionam carga útil insignificante e permitem você pagina ou busca novamente o item.
  • Alcance um índice de cobertura somente quando um padrão ativo lê alguns campos de itens grandes; pese primeiro o custo de gravação/armazenamento.

Construa o ProjectionExpression e seu mapa de nomes de atributos no Expression Builder, e tente DynoTable para executar essas projeções em suas próprias tabelas e observe a resposta diminuir.


  1. AWS DynamoDB Guia do desenvolvedor, Usando expressões de projeção em DynamoDB — a capacidade de leitura é baseada no tamanho do item antes de qualquer ProjectionExpression ser aplicado. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
  2. AWS DynamoDB Guia do desenvolvedor, Palavras reservadas em DynamoDB. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
  3. AWS DynamoDB Guia do desenvolvedor, Projeções de atributos (KEYS_ONLY / INCLUDE / ALL). https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html

Atualizado