DYNAMODB_SCAN - Escanear Tabela Completa
O que é este Node?
O DYNAMODB_SCAN é o node responsável por escanear toda a tabela DynamoDB ou aplicar filtros em atributos que não são chaves, retornando todos os itens que correspondem aos critérios.
Por que este Node existe?
Às vezes você precisa buscar dados sem saber a chave primária ou filtrar por atributos comuns. O DYNAMODB_SCAN existe para:
- Busca Flexível: Pesquisar por qualquer atributo, não apenas chaves
- Análise de Dados: Processar todos os registros da tabela
- Relatórios: Gerar estatísticas e agregações
- Manutenção: Encontrar e corrigir dados inconsistentes
Como funciona internamente?
Quando o DYNAMODB_SCAN é executado, o sistema:
- Autentica: Valida as credenciais AWS
- Inicia Scan: Começa a ler a tabela do início
- Lê Partições: Escaneia TODAS as partições sequencialmente
- Aplica Filtro: Se houver FilterExpression, filtra os itens após leitura
- Acumula Resultados: Coleta todos os itens que passam no filtro
- Limita: Para quando atingir o limite ou 1MB de dados
- Retorna: Array de itens + contagem
Código interno (aws-executors.service.ts:326-337):
case 'scan':
const scanResult = await dynamodb.scan({
TableName: data.tableName,
FilterExpression: data.filterExpression,
ExpressionAttributeValues: data.expressionAttributeValues,
Limit: data.limit,
}).promise();
return {
success: true,
items: scanResult.Items,
count: scanResult.Count,
};
Quando você DEVE usar este Node?
Use DYNAMODB_SCAN apenas quando realmente necessário:
Casos de uso
- Busca por atributo não-chave: "Encontrar todos os usuários com status = 'inativo'"
- Relatórios gerais: "Contar quantos produtos têm estoque < 10"
- Exportar dados: "Baixar toda a tabela para backup"
- Análise one-time: "Buscar emails duplicados em toda base"
Quando NÃO usar DYNAMODB_SCAN
- Sabe a Partition Key: Use DYNAMODB_QUERY ao invés (100x mais rápido)
- Buscar item específico: Use DYNAMODB_GET ao invés
- Tabelas grandes em produção: Scan pode levar minutos e custar caro
- Queries frequentes: Crie GSI (Global Secondary Index) e use QUERY
Parâmetros Detalhados
accessKeyId (string, obrigatório)
O que é: Chave de acesso da AWS.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Access Key",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Scan Tabela",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "Produtos",
"limit": 10
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Scan encontrou {{dynamodb_1.count}} itens"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 550, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Executa scan básico. Verá primeiros 10 itens da tabela.
secretAccessKey (string, obrigatório)
O que é: Chave secreta AWS.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Secret Key",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Iniciar",
"parameters": {
"message": "🔍 Iniciando scan da tabela..."
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Scan Completo",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "scan",
"tableName": "Usuarios"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "✅ Scan completo!\n\nTotal: {{dynamodb_1.count}} usuários"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Teste: Scan sem filtros retorna todos os usuários (até limite de 1MB).
region (string, obrigatório)
O que é: Região AWS da tabela.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Region",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "switch_1",
"type": "switch",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Escolher Região",
"parameters": {
"message": "Scanear em qual região?\n1️⃣ US\n2️⃣ Brasil",
"cases": [
{ "value": "1", "label": "US" },
{ "value": "2", "label": "BR" }
]
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Scan US",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "Logs",
"limit": 100
}
}
},
{
"id": "dynamodb_2",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 200 },
"data": {
"label": "Scan BR",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "scan",
"tableName": "Logs",
"limit": 100
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Scan concluído na região selecionada"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "switch_1" },
{ "source": "switch_1", "target": "dynamodb_1", "label": "1" },
{ "source": "switch_1", "target": "dynamodb_2", "label": "2" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "dynamodb_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Escolha região. Scan executa apenas naquela região.
tableName (string, obrigatório)
O que é: Nome da tabela a escanear.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Table Name",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Nome Tabela",
"parameters": {
"message": "Digite o nome da tabela para scanear:",
"variableName": "table_name"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Scan Dinâmico",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "{{table_name}}",
"limit": 50
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Tabela {{table_name}}: {{dynamodb_1.count}} itens escaneados"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite nome de tabela existente. Scan retorna até 50 itens.
filterExpression (string, opcional)
O que é: Expressão para filtrar itens APÓS leitura. Sintaxe similar a SQL WHERE.
Padrão: Nenhum (retorna todos os itens)
Operadores comuns:
- Comparação: =, <>, <, <=, >, >=
- Funções: begins_with(), contains(), attribute_exists(), attribute_not_exists()
- Lógicos: AND, OR, NOT
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Filter Expression",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Iniciar",
"parameters": {
"message": "🔍 Buscar produtos com estoque baixo"
}
}
},
{
"id": "number_1",
"type": "number",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Limite Estoque",
"parameters": {
"message": "Mostrar produtos com estoque abaixo de quantas unidades?",
"variableName": "stock_limit"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Scan com Filtro",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "Produtos",
"filterExpression": "estoque < :limit",
"expressionAttributeValues": {
":limit": "{{stock_limit}}"
}
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 700, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "⚠️ Produtos com estoque baixo: {{dynamodb_1.count}}\n\n{{#each dynamodb_1.items}}\n📦 {{this.nome}}\n📊 Estoque: {{this.estoque}} unidades\n---\n{{/each}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "number_1" },
{ "source": "number_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Teste: Digite um número (ex: 10). Verá apenas produtos com estoque < 10.
expressionAttributeValues (object, opcional)
O que é: Valores das variáveis usadas no filterExpression.
Padrão: Nenhum
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Expression Values",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Status",
"parameters": {
"message": "Buscar usuários com qual status? (ativo/inativo/bloqueado)",
"variableName": "user_status"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Scan por Status",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "scan",
"tableName": "Usuarios",
"filterExpression": "#status = :s",
"expressionAttributeValues": {
":s": "{{user_status}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Usuários com status '{{user_status}}': {{dynamodb_1.count}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite um status. Scan filtra apenas usuários com aquele status.
limit (number, opcional)
O que é: Número máximo de itens a retornar.
Padrão: Sem limite (até 1MB de dados)
Flow completo para testar:
{
"name": "Teste DynamoDB Scan - Limit",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "number_1",
"type": "number",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Limite",
"parameters": {
"message": "Quantos itens mostrar? (1-1000)",
"variableName": "scan_limit"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Scan Limitado",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "Logs",
"limit": "{{scan_limit}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Scan retornou {{dynamodb_1.count}} itens (limite: {{scan_limit}})"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "number_1" },
{ "source": "number_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite um número. Scan para após encontrar aquela quantidade.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| accessKeyId | string | Sim | Chave de acesso AWS |
| secretAccessKey | string | Sim | Chave secreta AWS |
| region | string | Sim | Região AWS |
| operation | string | Sim | Tipo de operação (sempre "scan") |
| tableName | string | Sim | Nome da tabela |
| filterExpression | string | Não | Filtro aplicado após leitura |
| expressionAttributeValues | object | Não | Valores dos placeholders |
| limit | number | Não | Máximo de itens a retornar |
Exemplo 1: Relatório de Estoque Baixo
Objetivo: Demonstrar scan com filtro para encontrar produtos que precisam reposição.
JSON para Importar
{
"name": "Relatório de Estoque Baixo - Scan",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Iniciar",
"parameters": {
"message": "📊 Relatório de Estoque\n\nBuscando produtos com estoque crítico..."
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Scan Estoque Crítico",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "scan",
"tableName": "Produtos",
"filterExpression": "estoque < :critico AND #status = :ativo",
"expressionAttributeValues": {
":critico": 10,
":ativo": "ativo"
}
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Tem Produtos?",
"parameters": {
"variable": "{{dynamodb_1.count}}",
"operator": ">",
"value": "0"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Alerta",
"parameters": {
"message": "⚠️ ALERTA DE ESTOQUE CRÍTICO!\n\nTotal: {{dynamodb_1.count}} produtos precisam reposição\n\n{{#each dynamodb_1.items}}\n📦 {{this.nome}}\n🔢 Código: {{this.codigo}}\n📊 Estoque: {{this.estoque}} unidades\n💰 Preço: R$ {{this.preco}}\n---\n{{/each}}\n\n🚨 Providenciar reposição urgente!"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 700, "y": 200 },
"data": {
"label": "OK",
"parameters": {
"message": "✅ Estoque OK!\n\nTodos os produtos ativos têm estoque adequado."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_2", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: 📊 Relatório de Estoque
Buscando produtos com estoque crítico...
Sistema: ⚠️ ALERTA DE ESTOQUE CRÍTICO!
Total: 3 produtos precisam reposição
📦 Notebook Dell
🔢 Código: PROD001
📊 Estoque: 5 unidades
💰 Preço: R$ 2999.00
---
📦 Mouse Logitech
🔢 Código: PROD015
📊 Estoque: 8 unidades
💰 Preço: R$ 89.90
---
📦 Teclado Mecânico
🔢 Código: PROD032
📊 Estoque: 3 unidades
💰 Preço: R$ 449.00
---
🚨 Providenciar reposição urgente!
Exemplo 2: Buscar Usuários Inativos há Mais de 30 Dias
Objetivo: Demonstrar scan com múltiplos filtros para encontrar usuários para reengajamento.
JSON para Importar
{
"name": "Buscar Usuários Inativos - Scan",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Iniciar",
"parameters": {
"message": "📧 Campanha de Reengajamento\n\nBuscando usuários inativos..."
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Calcular Data",
"parameters": {
"variableName": "thirty_days_ago",
"value": "2025-09-12"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_scan",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Scan Inativos",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "scan",
"tableName": "Usuarios",
"filterExpression": "ultimoAcesso < :date AND #status = :ativo",
"expressionAttributeValues": {
":date": "{{thirty_days_ago}}",
":ativo": "ativo"
},
"limit": 100
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 700, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "📊 Usuários Inativos Encontrados: {{dynamodb_1.count}}\n\n{{#each dynamodb_1.items}}\n👤 {{this.nome}}\n📧 {{this.email}}\n📅 Último acesso: {{this.ultimoAcesso}}\n---\n{{/each}}\n\n💡 Enviar campanha de reengajamento para estes usuários."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "variable_1" },
{ "source": "variable_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: 📧 Campanha de Reengajamento
Buscando usuários inativos...
Sistema: 📊 Usuários Inativos Encontrados: 12
👤 Maria Silva
📧 maria@example.com
📅 Último acesso: 2025-08-15
---
👤 João Santos
📧 joao@example.com
📅 Último acesso: 2025-08-20
---
...
💡 Enviar campanha de reengajamento para estes usuários.
Resposta do Node
{
"success": true,
"items": [
{
"productId": "PROD001",
"nome": "Notebook Dell",
"estoque": 5,
"preco": 2999.00,
"status": "ativo"
},
{
"productId": "PROD015",
"nome": "Mouse Logitech",
"estoque": 8,
"preco": 89.90,
"status": "ativo"
}
],
"count": 2
}
Diferença: Query vs Scan
QUERY (Preferível)
- ✅ Rápido - busca em 1 partição
- ✅ Barato - paga pelos itens retornados
- ✅ Eficiente - O(log n)
- ❌ Precisa de Partition Key
SCAN (Usar com cuidado)
- ⚠️ Lento - lê TODA a tabela
- ⚠️ Caro - paga por TODOS os itens lidos (mesmo os filtrados)
- ⚠️ Ineficiente - O(n)
- ✅ Funciona sem chaves
Exemplo: - Tabela: 1 milhão de itens - Filtro: estoque < 10 - Resultado: 50 itens
Query (com GSI): Lê 50 itens = $0.000005 Scan: Lê 1.000.000 itens, filtra 50 = $0.10 (20.000x mais caro!)
Boas Práticas
✅ SIM:
- Use Scan apenas quando absolutamente necessário
- SEMPRE coloque
limitem Scans para controlar custo - Execute Scans em horários de baixo tráfego
- Considere criar GSI (Global Secondary Index) se fizer Scan frequentemente
- Use parallel scan (no código) para tabelas muito grandes
- Pagine resultados para processar grandes volumes
❌ NÃO:
- Fazer Scan em produção sem limit
- Usar Scan para queries frequentes (crie GSI)
- Assumir que Scan retorna tudo de uma vez (limite de 1MB)
- Fazer Scan quando souber a Partition Key (use Query)
- Esquecer que FilterExpression consome RCUs mesmo para itens filtrados
Dicas
💡 Dica 1: FilterExpression é aplicado DEPOIS da leitura. DynamoDB cobra por todos os itens lidos, não apenas os retornados. Por isso Scan é caro!
💡 Dica 2: Se você faz Scan frequente no mesmo atributo, crie um GSI com aquele atributo como chave. Transforma Scan caro em Query barato.
💡 Dica 3: Use parallel scan (no código AWS SDK) para tabelas grandes. Divide tabela em segmentos e escaneia em paralelo (mais rápido).
💡 Dica 4: Para exportar/backup completo da tabela, use AWS Data Pipeline ou DynamoDB Export to S3 (mais eficiente que Scan manual).
💡 Dica 5: Combine limit com paginação para processar tabelas grandes sem timeout. Processe 100 itens por vez.
Próximo Node
→ DYNAMODB_QUERY - Buscar por Partition Key (mais eficiente) → DYNAMODB_UPDATE - Atualizar campos específicos → DYNAMODB_DELETE - Deletar itens