Intermediário8 min de leitura

DynamoDB Índices esparsos

Um índice esparso é um índice secundário que contém apenas os itens que carregam seu atributo chave - então, um subconjunto pequeno e quente de uma tabela enorme torna-se seu próprio coleção pré-filtrada e pronta para consulta.

Você tem milhões de linhas, mas a consulta executada o dia todo atinge uma pequena fatia: o tickets de suporte abertos, faturas não pagas, contas sinalizadas para revisão.

Filtrar essa fatia ainda verifica toda a tabela e cobra por cada leitura. Um o índice esparso torna o próprio índice pequeno.

O que é um índice esparso em DynamoDB?

Um índice esparso é um índice secundário que contém apenas os itens que carregam seu atributo chave. Como DynamoDB ignora qualquer item que falta nessa chave, você inventa uma chave que apenas os itens desejados escrevem – tickets abertos, faturas não pagas – e o índice se torna esse subconjunto exato. As consultas então lêem apenas, sem filtro, sem desperdício de capacidade de leitura.

  • Um índice secundário indexa apenas itens que possuem sua chave. Omita a chave em um item e nunca entra no índice — sem espaço reservado, sem linha nula.
  • Então você inventa uma chave que apenas os itens desejados carregam. Escreva nos itens que você consulta, remova-a do resto. O índice se torna exatamente esse subconjunto.
  • A consulta lê apenas o subconjunto, sem filtro. Seu tamanho rastreia o pequeno hot definido, não o total da tabela.
  • REMOVE é a alavanca, não o apagamento. Uma string vazia não é um índice válido key — DynamoDB rejeita toda a gravação com uma ValidationException — então você deve exclua o atributo.

O problema: a filtragem não salva leituras

Vindo de SQL, você assume que uma cláusula WHERE restringe o trabalho. DynamoDB FilterExpression não. Ele é executado após a leitura dos itens, não antes.

De acordo com AWS Guia do desenvolvedor, "um Query consome a mesma quantidade de capacidade de leitura, independentemente de um filtro expressão está presente" - você paga por cada item examinado e depois joga o não-jogos fora.

Portanto, se 50 dos seus 5 milhões de tickets estiverem abertos, um Query/Scan filtrado lê através de milhões para entregar a você esses 50.

Essa é a arma por trás de cada tópico "por que meu exame é tão caro"; consulta vs. varredura tem uma visão completa do custo.

Um índice esparso evita isso, tornando o próprio índice pequeno.

Como funciona a escassez

Um índice secundário indexa apenas itens que realmente possuem a chave do índice atributos.

O documentos AWS sobre índices esparsos explique isto: DynamoDB grava um item em um índice secundário somente quando esse item carrega os atributos-chave do índice, portanto, um índice sobre um atributo raramente definido permanece naturalmente pequeno.

Perde a chave de partição (ou chave de classificação) do GSI em um item e DynamoDB simplesmente não funciona escreva-o no índice. Nenhum espaço reservado, nenhuma linha nula — o item está ausente.

Essa “ausência por defeito” é o truque. Não indexe um atributo status que todo item carrega. Invente um atributo que apenas os itens que você deseja consulta é transportada .

O índice então se torna uma lista limpa exatamente desses itens e um Query contra ele lê apenas eles – sem filtro, sem desperdício de capacidade.

Imagine a tabela base alimentando o índice, onde apenas os itens que carregam a chave se cruzam:

chave removidachave removidaSparse GSI (open only)OpenOpenTabela base (todos os itens)Open: has keyOpen: has keyClosed: no keyClosed: no key

Somente os itens codificados (abertos) são replicados no índice; itens fechados nunca entram nele.

Esta é a mesma mentalidade de formação de chaves que design de tabela única: chaves são ferramentas que você cria para um padrão de acesso específico, não espelhos fiéis de seus dados.

Um exemplo prático: "somente tickets abertos"

Pegue uma mesa de tickets de suporte. A tabela base é codificada para buscar um ticket por id e listando os tickets de um cliente:

PKSKattributes
TICKET#a91fDETAILsubject, body, priority, openState
CUSTOMER#88TICKET#a91fsubject, priority, openState

Durante a vida útil da mesa, a maioria dos tickets acaba fechada. Mas a consulta do painel seus agentes fazem o dia todo é "mostre-me todos os tickets abertos, os mais antigos primeiro" - alguns cem linhas escondidas dentro de milhões.

Defina umcom chave de partição openBucket e chave de classificação openedAt e escreva apenas openBucket em tickets abertos. Defina-o quando o o ticket é criado; REMOVE quando o ticket for resolvido.

PKSKopenBucketopenedAt
TICKET#a91fDETAILOPEN2026-06-23T09:14:00Z← open: in the index
TICKET#b02cDETAILOPEN2026-06-22T16:40:00Z← open: in the index
TICKET#77deDETAIL(absent)2026-05-30T11:02:00Z← closed: NOT in the index

Os tickets a91f e b02c carregam openBucket, então eles ficam no GSI. Bilhete O 77de foi resolvido e o openBucket foi removido, então ele foi retirado silenciosamente. O dashboard agora é uma consulta barata:

Query  IndexName = "open-tickets-index"
KeyConditionExpression: openBucket = "OPEN"
ScanIndexForward: true        # oldest first

Isso lê apenas tickets abertos. À medida que os tickets fecham, o índice encolhe por si só – seu size rastreia a população aberta, nunca o total.

Um valor de partição estática ("OPEN") é adequado aqui precisamente porque o conjunto permanece pequeno. Um enorme conjunto aberto precisaria de uma chave de partição fragmentada, mas o "pequeno subconjunto" index é exatamente onde um valor é a chamada correta.

A transição que faz com que funcione é uma única- removendo o atributo quando o ticket for resolvido.

Crie um protótipo da cláusula REMOVE e da condição de chave digitada para o lado de leitura no DynamoDB Expression Builder, em vez de montando manualmente os espaços reservados ExpressionAttributeNames e :val você mesmo.

Faça isso no DynoTable

A parte difícil de um índice esparso é ver quais itens foram incluídos nele no índice versus o qual caiu silenciosamente.

DynoTable permite alternar uma visualização de tabela para um índice secundário e ver exatamente o subconjunto preenchido. Assim você pode confirmar que um ticket resolvido realmente foi deixado open-tickets-index em vez de permanecer com uma chave obsoleta.

A tabela de tickets de suporte visualizada através de seus tickets abertos GSI em DynoTable, mostrando apenas os itens que carregam a chave openBucket.
A tabela de tickets de suporte visualizada através de seus tickets abertos GSI em DynoTable, mostrando apenas os itens que carregam a chave openBucket.

Armadilhas e próximos passos

Algumas coisas para observar:

  • Remova a chave, não a deixe em branco. Uma string vazia não é uma chave de índice válida — escrever openBucket = "" falha com uma ValidationException, então o item nunca é indexado com ele. Para eliminar um item do índice você deve REMOVER o atributo.
  • O índice é. GSIs são atualizados de forma assíncrona, então um ticket recém-resolvido ainda pode aparecer brevemente — GSI lê suporta apenas consistência eventual. Não confie nisso para "este ticket está aberto agora".
  • Menteatributos. Um Query no índice retorna apenas o atributos projetados nele. Se o painel precisar de assunto e prioridade, projete-os - ou pague um GetItem extra pelo item base completo.
  • Tanto GSIs quanto LSIs podem ser esparsos — a alavanca é a mesma: omita o índice chave de classificação nos itens que você não deseja indexar. Um GSI geralmente é o melhor ajuste, porém: você pode adicioná-lo após a criação da tabela e fornecer seu próprio esquema de chave e capacidade. GSI vs. LSI analisa a compensação.

Índices esparsos são uma das ideias mais antigas do modelo. O original Artigo do Amazon Dynamo de 2007 construiu a loja atendendo a padrões de acesso conhecidos e de alto volume de maneira barata.

Um índice esparso é exatamente isso: modele as chaves para que a consulta comum não leia nada. não precisa.

Para construir e inspecionar um de verdade, download DynoTable, aponte-o para sua tabela e mude a visualização de dados para seu esparso GSI - observe a atualização do subconjunto como os itens ganham e perdem a chave do índice.

Atualizado