Intermediário9 min de leitura

Estratégias de sort key no DynamoDB: 3 padrões e quando usar cada um

Uma chave primária do DynamoDB é um ou dois atributos: uma sozinha, ou uma chave de partição mais uma chave de classificação. A chave de partição decide qual partição física guarda um item.

A chave de classificação decide a ordem dos itens dentro daquela partição — e essa ordenação é o que torna o Query poderoso.

Escolha a chave de classificação errada e você ainda consegue escrever dados, mas perde leituras de intervalo, ordenação e vários padrões de acesso de uma coleção.

Vindo do SQL você recorreria a um ORDER BY ou a um índice secundário depois do fato. No DynamoDB você grava a ordem na chave desde o início, ou não a tem.

Como funcionam as chaves de classificação do DynamoDB?

Uma chave de classificação do DynamoDB ordena os itens dentro de uma partição, então o Query pode fazer leituras de intervalo — >=, between, begins_with — em vez de buscar um item por vez. Chaves de classificação de string ordenam por bytes UTF-8 (Números ordenam numericamente), então projete uma chave de string (um timestamp ISO-8601, um número com zeros à esquerda) para que a ordem de bytes seja igual à ordem em que você quer ler.

  • A chave de classificação é seu índice dentro da partição. Ela ordena a em disco, então o Query pode fazer leituras de intervalo (>=, between, begins_with) em vez de um único GetItem.
  • Chaves de classificação de string ordenam por bytes UTF-8 (Números ordenam numericamente). Projete uma chave de string para que a ordem de bytes seja igual à ordem em que você quer ler — um timestamp ISO-8601, um número com zeros à esquerda, nunca um UUID cru ou 6/23/2026.
  • Uma chave de classificação bem-formada serve muitos padrões de acesso. Uma (EVT#<timestamp>) é um prefixo e um intervalo ao mesmo tempo — sem GSI necessário.
  • A direção é de graça. ScanIndexForward = false lê do mais novo ao mais antigo pelo mesmo custo; não armazene timestamps invertidos para simular isso.

Por que a chave de classificação é a alavanca

Sem uma chave de classificação, todo item de uma partição é endereçável apenas pela sua chave primária completa — um GetItem na melhor das hipóteses. Adicione uma chave de classificação e o DynamoDB armazena os itens ordenados por ela dentro da partição, o que desbloqueia o Query.

Isso significa condições de intervalo (>=, between), correspondência de prefixo (begins_with), e uma flag ScanIndexForward para ler em ordem ascendente ou descendente.

Segundo o AWS DynamoDB Developer Guide, todos os itens que compartilham uma chave de partição formam uma coleção de itens, ordenada em disco pela chave de classificação.

Então a chave de classificação não é só um segundo identificador. É o índice contra o qual você consulta dentro de uma partição.

Essa ordenação é a ordem de bytes na chave de classificação codificada: strings comparam por bytes UTF-8, números comparam numericamente. Este único fato guia quase toda estratégia abaixo.

Se você quer que consultas de intervalo signifiquem algo, a ordem de bytes tem que corresponder à ordem em que você quer ler.

Estratégia 1: torne a chave de classificação ordenável

O erro mais comum é uma chave de classificação que não é ordenada de forma significativa. Um UUID aleatório te dá unicidade, mas nenhuma consulta de intervalo útil — "me dê os últimos 20" se torna impossível porque a ordem de bytes é arbitrária.

Em vez disso, codifique o valor pelo qual você ordena e filtra dentro da chave de classificação, em uma representação cuja ordem de bytes seja igual à sua ordem lógica. Para timestamps isso significa um formato ordenável lexicograficamente: uma string ISO-8601 ou um epoch com zeros à esquerda.

O ISO-8601 foi projetado para que a comparação de strings seja igual à comparação cronológica — exatamente o que uma consulta de intervalo precisa. Evite formatos como 6/23/2026; eles ordenam errado no momento em que o mês vira.

Se você ordena por números (um contador de versão, uma pontuação), use o tipo Number nativo do DynamoDB em vez de uma string, para que 42 ordene depois de 9 em vez de antes dele.

Se um número precisa viver dentro de uma chave de classificação de string composta, preencha-o com zeros à esquerda até uma largura fixa.

Estratégia 2: chaves de classificação compostas para hierarquia

Uma chave de classificação pode codificar uma hierarquia concatenando segmentos com um delimitador, mais comumente #. Uma condição begins_with então seleciona uma subárvore inteira:

SK
EVENT#2026-06#01#login
EVENT#2026-06#03#export
EVENT#2026-07#02#login

begins_with(SK, "EVENT#2026-06#") retorna apenas os eventos de junho; o mais amplo begins_with(SK, "EVENT#") retorna todos eles.

A ordenação dos segmentos é uma decisão de design. Do grosso ao fino (ano → mês → dia) mantém itens relacionados contíguos, então uma leitura de intervalo permanece uma consulta barata em vez de uma dispersão pela partição.

Estratégia 3: controle a direção com ScanIndexForward

O DynamoDB armazena os itens em ordem ascendente de chave de classificação e os lê assim por padrão. Para ler do mais novo ao mais antigo — a ordem natural para um feed de atividade — defina ScanIndexForward = false no Query.

Isto é uma flag de tempo de leitura, não uma decisão de schema: a mesma coleção serve ambas as direções pelo mesmo custo. Não inverta seus timestamps (armazenando um "epoch reverso") só para obter leituras descendentes.

Uma coleção de itens, armazenada uma vez em ordem ascendente, lida de qualquer forma:

ScanIndexForward = trueScanIndexForward = falseColeção de itens (uma PK)SK EVT#09:00SK EVT#14:00SK EVT#next-dayMais antigo primeiroMais recente primeiro

Mesmos itens, mesma partição, mesmo custo — só a direção de leitura difere.

Exemplo trabalhado: um log de auditoria no escopo do ator

Suponha que você registre eventos com timestamp produzidos por atores — usuários, serviços, chaves de API — em um produto SaaS, e você tenha duas leituras:

  1. O fluxo de atividade de um ator, evento mais novo primeiro.
  2. Os eventos de um ator dentro de uma janela de tempo (ex.: "tudo entre os dois deploys"), para uma investigação.

Ambas as leituras estão no escopo de um único ator, então o ator é a chave de partição e o horário do evento é a chave de classificação. Use nomes de chave genéricos para que a mesma tabela possa guardar outras entidades depois:

PKSKattributes
ACTOR#u_8814EVT#2026-06-23T09:12:04Zaction=login, ip, ua
ACTOR#u_8814EVT#2026-06-23T14:05:11Zaction=export, target
ACTOR#u_8814EVT#2026-06-24T08:40:55Zaction=login, ip, ua
ACTOR#svc_billingEVT#2026-06-23T00:00:00Zaction=invoice.run

O prefixo EVT# mais um timestamp ISO-8601 dá uma chave de classificação ordenável. A leitura 1 é Query PK = "ACTOR#u_8814" com ScanIndexForward = false para o mais novo primeiro. A leitura 2 estreita a mesma partição com uma condição between na chave de classificação:

Query
PK = "ACTOR#u_8814"
AND SK BETWEEN "EVT#2026-06-23T00:00:00Z"
AND "EVT#2026-06-23T23:59:59Z"

Uma coleção, dois padrões de acesso, sem GSI — porque a chave de classificação é ao mesmo tempo um prefixo (EVT#) e um intervalo (o timestamp). A leitura descendente e a leitura da janela são os mesmos itens na mesma ordem; só os parâmetros diferem.

Montando essa condição de chave à mão, é fácil escorregar nos limites do between ou no escape de palavras reservadas nos nomes de atributo.

O Construtor de Expressões do DynamoDB gera a KeyConditionExpression, os ExpressionAttributeNames e os ExpressionAttributeValues para uma condição de chave de classificação begins_with ou between.

Copie-a direto para a sua chamada de SDK em vez de depurar escape em tempo de execução.

Faça isso no DynoTable

Projetar uma chave de classificação é iterativo: escreva alguns itens representativos, execute a consulta de intervalo e verifique se as linhas voltam na ordem que você espera. Fazer isso contra uma tabela ao vivo em uma GUI supera dar voltas pelo código.

Consultando a coleção de log de auditoria de um ator no DynoTable com uma condição between na chave de classificação, resultados ordenados do mais novo ao mais antigo.
Consultando a coleção de log de auditoria de um ator no DynoTable com uma condição between na chave de classificação, resultados ordenados do mais novo ao mais antigo.

Vire a direção de ordenação, aperte os limites do between e observe a coleção retornada mudar sem escrever uma linha de código — a forma mais rápida de confirmar um design de chave de classificação antes de você fechá-lo.

Armadilhas e próximos passos

  • Chaves de classificação devem ser únicas dentro de uma partição. Se dois eventos podem compartilhar um timestamp, anexe um desambiguador (um número de sequência ou id curto) à chave de classificação para que o composto permaneça único.
  • Uma partição quente não pode ser resolvida com ordenação. Se um ator produz muito mais eventos que os demais, a chave de classificação não vai te salvar — você precisa de um design de chave de partição que espalhe a carga. Veja single-table design.
  • Uma segunda ordem de classificação precisa de um segundo índice. A chave de classificação da tabela base dá uma ordenação. Para ordenar os mesmos itens de forma diferente (por tipo de evento, digamos), adicione um GSI com uma chave de classificação diferente — pesando os trade-offs de índice secundário local vs global.
  • Não recorra ao Scan para "ordenar depois". Ordenar no lado cliente após um Scan lê a tabela inteira e joga a ordenação fora; essa é a cilada do Scan. Empurre a ordem para dentro da chave de classificação em vez disso.

Uma vez que a condição de chave esteja certa, experimente o DynoTable para modelar a coleção, executar as consultas ascendente e descendente lado a lado, e verificar sua estratégia de chave de classificação contra dados reais antes de ela ir para produção.

Atualizado