Query vs Scan no DynamoDB
Query lê uma única coleção de itens pela chave de partição (opcionalmente estreitando a
chave de ordenação); Scan lê a tabela inteira e filtra depois. Eles parecem
similares na API, mas cobram — e escalam — de formas completamente diferentes.
Quando devo usar Query vs Scan no DynamoDB?
Use Query sempre que você conseguir nomear a partição que precisa — ele lê uma única coleção de itens e cobra apenas pelos itens correspondentes. Recorra ao Scan somente para exportações pontuais ou tabelas pequenas; ele lê cada item e cobra pela tabela inteira antes que qualquer FilterExpression seja executada. Em dados reais, o Query vence.
- Query é direcionado: você paga pelos itens da partição correspondente.
- Scan é exaustivo: você paga para ler cada item e depois descarta a maioria com um
FilterExpressionque roda depois que a leitura é tarifada.
Em uma tabela de qualquer tamanho real, um Scan com filtro é a clássica armadilha do "por que
minha conta está enorme e minha latência pior que a do RDS".
Lado a lado
| Query | Scan | |
|---|---|---|
| Leituras | Uma partição (por PK) | Todo item da tabela |
| Capacidade cobrada | Itens correspondentes na partição | Tabela inteira, antes de filtrar |
FilterExpression | Aplicado após a leitura — ainda cobrado pela leitura | Igual — filtrar nunca corta o custo |
| Latência | Constante conforme a tabela cresce | Cresce com o tamanho da tabela |
| Paginação | 1 MB/página → LastEvaluatedKey | 1 MB/página; paralelizável |
| Use para | Padrões de acesso conhecidos | Exportações pontuais, tabelas mínimas |
A pegadinha-chave: um FilterExpression roda depois que o DynamoDB tarifa a leitura, em
ambas as operações. Um Scan que "retorna 10 linhas" pode cobrar pela leitura de um milhão —
filtrar é uma conveniência, nunca um controle de custo.
Use Query
Query PK = "USER#42" AND SK begins_with "ORDER#"
Se você se pegar recorrendo ao Scan para responder a um padrão de acesso comum, isso
é um sinal de modelagem: adicione um Global Secondary Index para que o
padrão vire um Query.
A escolha se resume a uma pergunta — você consegue nomear a partição que precisa?
Se a chave é conhecida você usa Query; se não, adicione um GSI para torná-la um, e recorra ao Scan só quando nenhuma chave servir.
Quando o Scan é aceitável
Exportações pontuais, tabelas de configuração mínimas e jobs em segundo plano que paginam por
toda a tabela de propósito. Use Segment/TotalSegments para dividir um Scan entre
workers (um scan paralelo) quando você genuinamente precisa ler tudo.
Um SELECT * FROM table reflexivo sobre o DynamoDB é o mesmo anti-padrão em
roupagem PartiQL — ele compila para um Scan. Quando você realmente precisa de
análises entre itens (um GROUP BY, um JOIN, uma agregação), o SQL Workbench do DynoTable os roda
no lado do cliente sobre um conjunto de resultados limitado, em vez de martelar a tabela.
Estime as unidades de leitura que cada padrão vai custar com a calculadora de capacidade e experimente o DynoTable para rodar e inspecionar essas consultas contra suas próprias tabelas.