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
#namepara 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
Queryque 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:
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.
ProjectionExpression | Cobertura GSI | |
|---|---|---|
| Reduz a carga útil | Sim | Sim |
| Reduz custos de leitura | Não | Sim — leia no tamanho do índice |
| Armazenamento extra | Nenhum | Uma segunda cópia dos campos projetados |
| Custo extra de gravação | Nenhum | As gravações são propagadas para o índice |
| Melhor para | Ocultando campos privados; pequenas vitórias | Leituras 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
nomeoustatussimples 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.
- 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
ProjectionExpressionser aplicado. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html ↩ - AWS DynamoDB Guia do desenvolvedor, Palavras reservadas em DynamoDB. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html ↩
- AWS DynamoDB Guia do desenvolvedor, Projeções de atributos (
KEYS_ONLY/INCLUDE/ALL). https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html ↩