Iniciante9 min de leitura

Como contar, somar e agregar em DynamoDB

DynamoDB tem exatamente um agregado integrado: contar itens correspondentes com Selecione=CONTAR. Não há SUM, AVG, MIN ou MAX nativos. E até a contagem você pode obter leituras (e cobranças) de cada item contado. Este guia cobre o que é realmente suportado, as aproximações que as pessoas alcançam e como executar COUNT/SUM/AVG em uma tabela quando você precisar deles.

DynamoDB pode fazer SUM, COUNT e funções agregadas?

Principalmente não. O único agregado integrado de DynamoDB é Select=COUNT, que retorna contagens de itens correspondentes, mas ainda lê (e cobra) cada item. Não há nenhum SUM, AVG, MIN ou MAX nativo, e PartiQL também não adiciona nenhum. Para agregados reais com GROUP BY, dobre-os em seu aplicativo, mantenha um contador ou execute SQL no Workbench de DynoTable.

  • Select=COUNT retorna o número de itens correspondentes, mas DynamoDB ainda lê cada item para produzi-lo - você paga o custo total de leitura Scan/Query, não um custo barato de "contagem".
  • Não há operações de leitura nativas SUM, AVG, MIN ou MAX. DynamoDB devolver itens; eles não os dobram em um número. PartiQL não adiciona agregados também.
  • DescribeTable.ItemCount é gratuito, mas apenas aproximado e atualizado "aproximadamente a cada seis horas" — bom para um bloco de painel, errado para qualquer coisa exato.
  • Para COUNT/SUM/AVG/MIN/MAX exato (com GROUP BY), agregue em seu app, mantenha um contador ou execute-o no SQL Workbench de DynoTable (abaixo).

Contando itens: Select=COUNT

Ambos Query e Scan aceitam um parâmetro Select. Defina-o como COUNT e o resposta carrega as contagens em vez dos itens:

aws dynamodb scan \
  --table-name Orders \
  --select COUNT \
  --filter-expression "#s = :open" \
  --expression-attribute-names '{"#s":"status"}' \
  --expression-attribute-values '{":open":{"S":"OPEN"}}'

A resposta fornece dois números (AWS: Contando os itens nos resultados):

  • Count — "o número de itens que permanecem, após uma expressão de filtro (se presente) foi aplicado."
  • ScannedCount — "o número de itens avaliados, antes de qualquer ScanFilter é aplicado." Sem filtro, ScannedCount é o mesmo que Count.

Se você tiver apenas oe precisa contar duplicatas dentro dele, o condição + filtro que você passa é exatamente o que DynamoDB Expression Builder gera — o Mapas FilterExpression e ExpressionAttributeNames/Values acima, mais o KeyConditionExpression quando você conta dentro de uma partição via Query — sem escapando manualmente do JSON.

Mais duas pegadinhas que mordem as pessoas contando mesas grandes:

  • O limite de página de 1 MB ainda se aplica. "Se o tamanho do conjunto de resultados Scan for maior que 1 MB, ScannedCount e Count representam apenas uma contagem parcial de o total de itens" (documentos AWS Scan). Você precisa paginar alimentando LastEvaluatedKey de cada resposta como o ExclusiveStartKey da próxima solicitação, mantendo um total em execução para obter o real número - o mesmo loop coberto em paginação DynamoDB.
  • Um Query estreito vence um Scan. Select=COUNT em um Query mede apenas o itens na partição de destino, não na tabela inteira. Se você pode fixar uma partição chave (tabela base ou GSI), conte lá - é o Query-vs-Scan lacuna de custo aplicada à contagem.

Select=COUNT vs ItemCount (e por que está obsoleto)

DescribeTable retorna um ItemCount (e TableSizeBytes) gratuitamente, sem custo de leitura. O problema está no API faz referência a si mesmo: "DynamoDB atualiza este valor aproximadamente a cada seis horas. Mudanças recentes podem não ser refletido neste valor." Portanto, pode ficar bem atrás do estado real da sua tabela.

Selecionar=CONTARDescribeTable.ItemCount
ExatidãoExato (para o conjunto correspondente)Aproximado
FrescuraAo vivoAtualizado ~a cada 6 horas
CustoLê + fatura cada item contadoGrátis (metadados)
Pode filtrar/contar um subconjuntoSim (expressão de filtro)Não — apenas tabela inteira

Use ItemCount para uma verificação aproximada de "qual o tamanho desta tabela" ou um bloco do painel. Use Select=COUNT quando precisar de um número exato, filtrado ou atual — e aceite o custo de leitura. Para qualquer coisa verdadeiramente viva e gratuita, monitore você mesmo um contador (veja Padrões de agregação abaixo).

Por que não existe SUM/AVG/MIN/MAX nativo

As operações de leitura de DynamoDB retornam itens. Não há planejador de consultas para dobrar um resultado definido em um escalar, então não há nada para calcular um SUM ou AVG. Contar é a única dobra que API oferece, via Select=COUNT.

PartiQL não muda isso. O PartiQL gramática SELECT é SELECT {{expression}} [,…] FROM {{table}}[.{{index}}] [WHERE…] [ORDER BY {{key}} …], onde a expressão é "uma projeção formada a partir do curinga * ou uma projeção lista de um ou mais nomes de atributos ou caminhos de documentos." Não há agregado função e nenhuma cláusula GROUP BY nessa gramática - e ORDER BY leva uma {{key}}, documentado como "uma chave hash ou uma chave de classificação a ser usada para ordenar os resultados retornados". Cada PartiQL SELECT ainda compila para um GetItem, Query ou Scan, então SELECT SUM(total) FROM "Orders" simplesmente não pode ser expresso. (Mais sobre o PartiQL teto em PartiQL vs SQL.)

Padrões de agregação (contadores, fluxos, lado do aplicativo)

Como DynamoDB não agregará para você, os padrões estabelecidos impulsionam o trabalho em outro lugar:

  • Item de contador mantido. Mantenha um item dedicado (por exemplo, PK = "STATS#orders") e ADD a um atributo numérico em cada gravação com um UpdateItem. Lendo o agregado é então um único GetItem - exato e barato, mas você possui o incremento lógica, sua consistência e a contenção se um contra-ataque for derrotado.
  • alimentando um agregador. Habilite um stream e conecte-o a um Lambda que atualiza totais em execução (contagens, somas) à medida que os itens mudam. De acordo com AWS Documentos de streams, você pode configurar o StreamViewType do stream para que cada registro carregue o NEW_AND_OLD_IMAGES — "as imagens novas e antigas do item" — o suficiente para manter os agregados no estilo SUM atualizados sem nova verificação. Os registros de fluxo estão sujeitos para uma vida útil de 24 horas ("os registros de fluxo dentro de um fragmento são removidos automaticamente após 24 horas"), então o consumidor tem que acompanhar.
  • Dobra no lado do aplicativo. Percorra os itens correspondentes e acumule os SUM/AVG/MIN/MAX em seu próprio código. Correto, mas lê (e cobra) cada item sempre — o mesmo perfil de custo de Select=COUNT, mais os dados transferência.
  • Descarregue para análise. Para agregação analítica pesada ou ad hoc, exporte o tabela para o S3 e consultá-la com o Athena ou transmiti-la para um warehouse. De acordo com documentos AWS exportar para S3, exportar "não consome unidades de capacidade de leitura" e permite "realizar análises e consultas complexas usando serviços AWS como Athena" — o caminho recomendado por AWS uma vez você superou a agregação por solicitação.

Cada um troca simplicidade por escrituração contábil em tempo de gravação (contadores, fluxos) ou custo do tempo de leitura (verificações do lado do aplicativo). Nenhum padrão faz com que o próprio DynamoDB calcule uma SUM de graça. A versão de agrupamento desta compensação - agregar por chave em vez de sobre toda a mesa - é o seu próprio guia: DynamoDB GROUP BY.

Executando COUNT/SUM/AVG em DynoTable's SQL Workbench

Quando você só precisa da resposta - "quantos pedidos ABERTOS e qual é o total" - sem escrever um loop de varredura de paginação ou um Lambda, DynoTable's SQL Workbench executa agregados reais. Ele materializa suas tabelas através do real DynamoDB Query/Scan tempo de execução e, em seguida, executa um único SELECT no topo - agregados, GROUP BY, HAVING, DISTINCT: SQL dentro das regras de padrão de acesso de DynamoDB.

-- Runs in the DynoTable Workbench (NOT in PartiQL):
SELECT status,
       COUNT(*)        AS orders,
       SUM(total)      AS revenue,
       AVG(total)      AS avg_order,
       MIN(total)      AS smallest,
       MAX(total)      AS largest
FROM orders
GROUP BY status
ORDER BY revenue DESC

Isso é COUNT, SUM, AVG, MIN, MAX, GROUP BY e ORDER BY em um agregado computado - nenhum dos quais DynamoDB ou PartiQL pode expressar (PartiQL's ORDER BY é limitado aos atributos-chave) - em uma instrução. Isto é o mesmo cunha analítica como SQL para DynamoDB; para o completo história de agrupamento, consulte DynamoDB GROUP BY.

O Workbench é honesto sobre o modelo de acesso abaixo, não um falso Postgres:

  • As linhas ainda passam pelo Query/Scan real de DynamoDB. Um GROUP BY sobre um todo tabela ainda é um Scan embaixo - as superfícies Workbench que custam em vez de escondendo-o, a mesma compensação Query-vs-Scan.
  • As agregações são executadas nos atributos escalares materializados depois que as linhas chegam.

FAQ

Posso contar itens em DynamoDB sem digitalizar? Não exatamente. Para uma contagem exata e atual, você deve ler os itens - Select=COUNT ainda mede cada item contado. As únicas opções sem digitalização são as DescribeTable.ItemCount aproximado (atualizado ~a cada 6 horas) ou um item de contador que você mantenha-se em cada gravação.

Como posso contar itens por GSI? Execute Query (ou Scan) no índice com Select=COUNT. Contando através de um partição estreita GSI é muito mais barata do que escanear a tabela base, porque você só leia os itens nessa partição de índice – modele o índice em torno da contagem necessária.

O DescribeTable.ItemCount é preciso? É aproximado. O Referência API afirma que DynamoDB atualiza ItemCount e TableSizeBytes "aproximadamente a cada seis horas" e "as alterações recentes podem não estar refletidas neste valor". Não use onde um número exato ou real é importante.

O DynamoDB pode fazer SUM ou AVG? Não nativamente, e não em PartiQL — o PartiQL gramática SELECT não tem funções agregadas. Agregue na sua aplicação, mantenha um contador (opcionalmente via DynamoDB Streams), ou execute SUM/AVG em DynoTable's SQL Workbench.

Qual é a diferença entre Count e ScannedCount? ScannedCount é quantos itens DynamoDB avaliados antes do seu filtro; Contar é quantos permanecem depois disso. Eles são iguais quando não há expressão de filtro. Um grande a lacuna entre eles significa uma contagem ineficiente.


Precisa somar, calcular a média ou agrupar seus dados DynamoDB sem escrever um loop de varredura? Baixe DynoTable e execute-o em uma aba Workbench. Comparando clientes primeiro? Veja onde ele chega em uma GUI DynamoDB simples.

Atualizado