Intermediário6 min de leitura

Ordenar o DynamoDB por um Atributo que Muda (Mutável)

Você modela uma chave de ordenação em torno de um atributo para poder consultar itens na ordem dele — e então o atributo muda. O status de um chamado, o estado de um pedido, a prioridade de uma tarefa. Eis a pegadinha que o DynamoDB impõe: você não pode atualizar um atributo de chave no lugar. Uma chave primária é imutável por toda a vida do item. Mude um valor que faz parte da chave e você não está editando um item — está movendo-o, e o DynamoDB obriga você a fazer isso explicitamente.

É possível alterar uma sort key no DynamoDB?

Não. A sort key faz parte da chave primária, e os atributos de chave do DynamoDB são imutáveis — UpdateItem não pode editar o valor de uma partition key ou sort key, e não existe operação de "mover item". Para alterá-la, você precisa apagar o item antigo e criar um novo, ou manter o valor volátil em uma sort key de GSI.

  • Atributos de chave são imutáveis. Você não pode fazer UpdateItem no valor de uma chave de partição ou de ordenação — o DynamoDB não tem operação de "mover item".
  • Para mudar o valor de uma chave você apaga o item antigo e coloca um novo — idealmente em uma transação para que seja atômico.
  • Melhor: mantenha o valor volátil fora da chave da tabela base e coloque-o numa chave de ordenação de GSI — chaves de GSI podem mudar, porque atualizar o item base apenas re-propaga a entrada do índice.
  • Escolha chaves de ordenação que não mudam (timestamps, ids imutáveis) sempre que o padrão de acesso permitir.

O problema: um status pelo qual você quer ordenar, que vive mudando

Digamos que você opere um suporte e queira listar os chamados de uma equipe ordenados por status, então você coloca o status na chave de ordenação:

PK: TEAM#7   SK: STATUS#open#TICKET#8842

Agora o chamado passa para pending. Você gostaria de só fazer UpdateItem na chave de ordenação para STATUS#pending#TICKET#8842 — mas o DynamoDB rejeita qualquer escrita que mude um atributo de chave. A chave é o endereço do item; você não pode editar o endereço no lugar. O status que você escolheu para ordenar é justamente a coisa que não fica parada.

Opção 1: apagar e recriar (atomicamente)

Se o valor precisa viver na chave da tabela base, mudá-lo significa remover o item antigo e escrever o novo:

1. DeleteItem  PK=TEAM#7  SK=STATUS#open#TICKET#8842
2. PutItem     PK=TEAM#7  SK=STATUS#pending#TICKET#8842  (same attributes)

Faça isso dentro de um TransactWriteItems para que o delete e o put ou ambos tenham sucesso ou ambos falhem — caso contrário, uma falha entre eles perde o chamado ou o duplica. Isso funciona, mas toda mudança de status agora são duas escritas mais uma transação; tudo bem para mudanças ocasionais, caro para as muito frequentes.

Opção 2: manter o valor mutável fora da chave base (preferido)

O design mais limpo: faça a chave da tabela base ser algo imutável (o id do chamado) e coloque o valor volátil e ordenável numa chave de ordenação de GSI.

Base:  PK: TICKET#8842   status: "open"   teamId: TEAM#7
GSI:   GSI1PK: TEAM#7    GSI1SK: STATUS#open#TICKET#8842

Agora mudar o status é um UpdateItem simples no atributo status do item base — o que o DynamoDB permite, porque status não é uma chave da tabela base. O DynamoDB então re-propaga a entrada do GSI automaticamente para a sua nova posição ordenada. Uma escrita, sem transação, sem a dança do delete.

SimNão, é uma chave de ordenaçãode GSIStatus muda de open parapendingO valor está numa chave databela base?Apagar + recriar numa transaçãoUpdateItem simples; o GSIre-propaga

O trade-off: o GSI tem consistência eventual e custa armazenamento/escritas extras — mas para um valor que muda com frequência, isso é bem mais barato do que apagar-e-recriar a cada mudança.

Projetando as chaves no DynoTable

Monte e pré-visualize as key conditions tanto para a leitura base quanto para a leitura do GSI no construtor de expressões do DynamoDB.

No DynoTable, você então escolhe por qual índice uma consulta passa e observa o valor volátil ordenando no GSI enquanto o item base mantém sua chave imutável — ambas as leituras lado a lado em dados reais.

Consultando um GSI ordenado por status enquanto o item base mantém uma chave imutável no DynoTable.
Consultando um GSI ordenado por status enquanto o item base mantém uma chave imutável no DynoTable.

Armadilhas e próximos passos

  • Nunca tente fazer UpdateItem em um atributo de chave — é rejeitado; valores de chave são fixos por toda a vida do item.
  • Se você precisar movê-lo, faça delete+put numa transação — nunca como duas escritas desprotegidas.
  • Prefira chaves base imutáveis + um GSI para qualquer atributo pelo qual você ordena e que muda.
  • Não esqueça da consistência eventual do GSI — a entrada reordenada aparece após um breve atraso de propagação.
  • Relacionado: estratégias de chave de ordenação, GSI vs LSI, transações.

Quer ver como um atributo mutável ordena num GSI versus na tabela base? Baixe o DynoTable e explore seus índices diretamente.

Atualizado