O blog da AWS

Usando chaves de classificação para organizar dados no Amazon DynamoDB

Por AM Grobelny , Senior Technical Evangelist na AWS

 

É fácil começar a preencher uma tabela do Amazon DynamoDB com dados. No entanto, sem um planejamento da organização dos dados, você pode limitar as suas opções de consulta de dados posteriormente.

Organização de dados e planejamento de consulta de dados são etapas críticas ao projetar uma tabela. Sem organização de dados adequada, as únicas opções para consultar dados são consulta por chave de partição ou varredura (scan) de todos os registros na tabela. Esses métodos de consulta são limitados ou dispendiosos em termos de preço (RCUs) e desempenho.

Neste post, exploro exemplos reais de otimização de tabelas para consultar dados com chaves de classificação (sort keys). A chave de classificação não é usada apenas para agrupar e organizar dados, mas também para fornecer meios adicionais para consultar itens em uma tabela.

 

Uma breve introdução às chaves de partição

Para entender melhor como organizar seus dados, é importante entender como os dados são armazenados no DynamoDB. Cada item em uma tabela do DynamoDB requer que você crie uma chave primária para a tabela, conforme descrito na documentação do DynamoDB. Uma chave primária pode ser uma chave de partição (partition key) ou uma combinação de chave de partição e chave de classificação (sort key). A chave primária deve ser exclusiva em toda a tabela.

Ao usar apenas uma chave de partição como chave primária, uma escolha abaixo do ideal para uma chave de partição pode afetar o desempenho geral da tabela. Por exemplo, consultar frequentemente a mesma chave primária pode causar exceções que excedem a capacidade de leitura (RCU) configurada para a tabela.

Para obter mais informações sobre chaves de partição e suas melhores práticas, consulte a publicação no Blog do banco de dados da AWS.

 

Usando chaves de classificação para expandir as opções de consulta de dados

Em alguns casos, apenas uma chave de partição pode ser fornecida como chave primária ao criar uma tabela. Nesses casos, você está limitado a consultar dados usando a chave de partição como o único critério de consulta ou retornar todos os itens na tabela com a operação de varredura. Criar uma tabela como essa é simples e, em alguns casos, tudo o que você precisa é simples.

No entanto, à medida que o conjunto de dados cresce, as varreduras de tabela podem se tornar um fardo dispendioso em termos de preço e desempenho. As varreduras de tabela podem esgotar rapidamente sua capacidade de leitura e, portanto, aumentar sua fatura. Para obter mais informações sobre unidades de capacidade de leitura e gravação e como essas unidades afetam sua fatura do DynamoDB, consulte Definição de preço do Amazon DynamoDB e Modo de capacidade de leitura e gravação na documentação do DynamoDB. Além disso, nem sempre é possível consultar itens apenas com a chave de partição. Considere os exemplos de consultar pedidos de clientes antes de uma data específica e visualizar todos os produtos que correspondem a uma categoria. Adicionar uma chave de classificação a uma tabela abre mais opções de consulta de dados além de varreduras e por chaves de partição.

Observe que as chaves de classificação não são usadas apenas para determinar a ordem dos itens retornados por uma consulta. Como mostra esta publicação, as chaves de classificação não estão diretamente vinculadas à classificação de itens para consulta, mas expandem as opções de consulta de dados.

A combinação de uma chave de partição e uma chave de classificação cria uma chave composta, e essa chave composta se torna a chave primária de itens individuais em uma tabela. Com uma chave composta, você tem a capacidade de usar consultas com uma expressão de condição principal (KeyConditionExpression) contra a chave de classificação. Em uma consulta, você pode usar KeyConditionExpression para escrever instruções condicionais usando operadores de comparação que são avaliados com base em uma chave e limitar os itens retornados. Em outras palavras, você pode usar operadores especiais para incluir, excluir e corresponder itens com base em seus valores de chave de classificação.

Vejamos um exemplo de consultas com uma chave de classificação e consultas por tempo. Suponha que a chave de classificação de uma tabela específica seja um Unix timestamp (Era Unix) armazenado como número. Nesse caso, você pode realizar uma consulta com uma condição de chave que retorna todos os itens antes de um horário específico usando o operador de comparação menor que (<). Vou abordar este exemplo de consulta com intervalos de tempo mais tarde.

 

Trabalhando com intervalos

Intervalos com chaves de classificação são usados para criar consultas. Os seguintes operadores estão disponíveis em consultas com KeyConditionExpression:

  • =
  • <
  • >
  • <=
  • >=
  • between
  • begins_with

O operador between aceita dois valores para determinar um intervalo, e o operador begins_with verifica se uma string começa com uma determinada substring. Você pode usar a maioria desses operadores em valores numéricos, mas o operador begins_with permite algumas maneiras interessantes de consultar dados.

Por exemplo, considere como agrupar locais. Nos Estados Unidos, os locais geralmente são agrupados por cidade, estado, e país. Suponha que criemos uma chave de classificação que armazena a localização de um item em uma cadeia usando o modelo cidade-estado-país.

A ordem da cidade-estado-país começa com a parte mais específica dos dados de localização (cidade). Como resultado, suas consultas com o operador begins_with estão limitadas à cidade. Se eu alterar a ordem da cadeia de localização para país–estado-cidade, o operador begins_with fornece três níveis de consulta:

  • begins_with (EUA) — Retorna todos os itens localizados nos Estados Unidos
  • begins_with (USA-TX) — Retorna somente itens localizados no Texas.
  • begins_with (USA-TX-Houston) — Retorna apenas itens localizados em Houston.

Ao agrupar locais dessa maneira, você só está limitado por sua engenhosidade.

 

Como usar chaves de classificação para organizar e consultar dados

Aplicar o conhecimento de chaves de classificação a exemplos da vida real destaca técnicas e padrões repetíveis que você pode usar para organizar e consultar dados em tabelas criadas no futuro.

Vamos primeiro considerar dados de registros (logs), como monitoramento de eventos, eventos de filas de subscrição (publisher/subscriber), logs de serviço, e similares. Exemplos de fontes de dados podem ser sequências de cliques, logs do systemd, ou APIs de sistemas de produtividade corporativa (ERP) e plataformas de software como serviço (SaaS), como o Salesforce.

Exemplo 1: Trabalhando com dados de registros (logs)

Começo com um exemplo simples e implemento o conceito de marcadores de tempo que mencionei anteriormente ao discutir marcadores de tempo Unix Suponha que os dados de telemetria são coletados de vários dispositivos. Cada dispositivo tem um ID de dispositivo, um ID de evento para cada evento exclusivo, e um marcador de tempo (timestamp). Os registros geralmente têm dados de tempo associados a eventos capturados no log. Normalmente, os logs são consultados consultando um intervalo de tempo específico.

Vá para o console do DynamoDB e crie uma nova tabela. Para organizar logs de eventos, forneça uma chave de partição exclusiva de serviço que criará os registros de dados, conforme mostrado na captura de tela a seguir. Por exemplo, a chave de partição pode ser um nome de host ou um valor para DeviceID. Para a chave de classificação, forneça o valor de timestamp do evento individual.

 

 

Você pode emitir consultas usando o operador between e dois valores de timestamp, o operador >, ou o operador <. Conforme mostrado na captura de tela a seguir, três registros são armazenados para um dispositivo com o DeviceID de valor 123. As datas armazenadas como Unix timestamp são equivalentes a 29 de agosto de 2018, 12:00 p.m. UTC; 4 de setembro de 2018, às 1:00 UTC; e 9 de julho de 2011, às 13:00 UTC. Para converter timestamps em formatos legíveis para humanos, consulte o site unixtimestamp.

 

 

Eu fiz uma consulta filtrando logs com timestamps antes de 4 de setembro de 2018, às 12:00 a.m. UTC usando o operador < e o timestamp: 1536019200.

 

 

Exemplo 2: Trabalhando com mensagens de bate-papo

Este exemplo é baseado no conceito de usar uma string de modelo para a chave de classificação. Lembre-se do exemplo de dados de localização que falei anteriormente. Para este novo caso, considere que os dados vêm de um aplicativo de bate-papo. Para referência, digamos que os usuários tenham um nome de usuário e as salas de bate-papo tenham identificadores exclusivos e você queira armazenar cada mensagem de bate-papo. Quero ser capaz de consultar mensagens por usuário e também por usuário e tempo.

O ChatRoomID pode servir como chave de partição. Se você tiver uma sala de bate-papo movimentada, poderá adicionar um sufixo numérico crescente ao ChatRoomID, como seattle-1 ou seattle-2 para distribuir o acesso a dados entre partições. Essa prática pode lhe ajudar a evitar problemas relacionados à criação de uma partição ativa (partição quente). Para obter mais informações sobre partições ativas e selecionar a melhor chave de partição para uma tabela, consulte Escolhendo a chave de partição correta do DynamoDB no blog do banco de dados da AWS.

A chave de classificação composta deve seguir este formato: user_name#datetime. Para o valor de datetime, a representação de string do tipo aaaa-mm-dd:HH:MM:SS fornece a maior quantidade de opções de consulta.

 

 

Neste exemplo, as mensagens são armazenadas para dois usuários em vários momentos, conforme mostrado na captura de tela a seguir.

 

 

A criação da chave de classificação composta fornece algumas opções para realizar consultas com o operador begins_with. Você pode visualizar mensagens filtradas por sala e usuário.

 

 

A parte da data da string do modelo ChatMessageIdentifier é organizada da menos específica (ano) para a mais específica (segundos). Você pode visualizar mensagens em uma sala de bate-papo por usuário e retornar todas as mensagens de um ano (amsg#2018) ou um ano e mês específicos (amsg#2018 -08), por exemplo.

 

 

As consultas vêm com vantagens e limitações. Por exemplo, você não pode consultar dados com base no tempo aqui porque optamos por iniciar a string do modelo com user_name. Se o tempo for um fator de consulta mais importante para você, você pode classificar sua string de modelo de forma diferente ou adicionar um índice secundário, com uma chave de classificação adicional que reverte a string do modelo original para: datetime#user_name.

Exemplo 3: Rastreamento de documentos

Por fim, considere um caso de uso mais avançado em que a chave de classificação é um valor arbitrário e pode mudar para ajudá-lo a consultar diferentes conjuntos de dados sobre o mesmo objeto. Eu uso o exemplo real de um sistema de rastreamento de documentos. Os sistemas de rastreamento de documentos geralmente retêm dados sobre quem tem permissões para acessar um documento, em qual versão está o documento, onde o documento está armazenado e metadados sobre o documento. Eu defini a chave de partição como uma ID exclusiva vinculada ao documento, e usei a chave de classificação para representar cada uma dessas variáveis no sistema de rastreamento de documentos.

 

 

Com essa chave de classificação genérica, mas contextual, posso permitir que metadados (metadata) arbitrários sejam armazenados na chave de classificação e consultados. Ou posso usar o campo da chave de classificação para armazenar identificadores de acesso para estipular quem pode acessar este documento com o valor das permissões (permissions). Em vez de predefinir o esquema do banco de dados, posso permitir que meu aplicativo forneça o contexto de que tipo de dados estou armazenando sobre documentos. Com essa flexibilidade, meu aplicativo pode fornecer a definição dos dados em vez do banco de dados.

 

 

Como você pode ver na captura de tela acima, a estrutura dos dados difere para cada item e armazena as informações relevantes para cada valor de chave de classificação arbitrária. Para consultar um desses itens, uma consulta é realizada usando o operador = com o tipo de informação de documento que eu preciso. Por exemplo, para recuperar metadados do documento, uso o operador = e metadata de valor para minha consulta.

 

 

Com base neste exemplo de rastreamento de documentos, vamos abordar um caso de uso avançado para a chave de classificação. Posso usar a mesma chave de classificação documentInfo para implementar o controle de versão do documento. Mais uma vez, usando o operador begins_with com uma string de modelo, crio itens na tabela para cada versão de um documento. O valor da chave de classificação adere ao seguinte modelo: v_#, onde # é o ID da versão ou o número da versão do documento. O valor da chave de classificação v_0 é reservado para armazenar a versão mais recente do documento e é sempre uma linha duplicada de qualquer versão do documento que foi adicionada pela última vez. Neste exemplo, v_0 armazena os mesmos dados que v_2, porque v_2 é a última versão do documento.

Com esse padrão, você pode consultar o histórico completo de documentos utilizando begins_with (v_), conforme mostrado na captura de tela a seguir.

 

 

Conclusão

A chave de classificação pode adicionar mais poder aos recursos de consulta do DynamoDB. No entanto, você deve fazer uma análise e planejamento prévios. Lembre-se de usar modelos de string que aproveitam o operador begins_with e classificam os dados a partir da informação menos específica para a mais específica. A chave de classificação também pode armazenar valores de string exclusivos e arbitrários, como metadados e permissões para auxiliar em consultas subsequentes.

Sinta-se à vontade para usar dados do DynamoDB em conjunto com outros serviços quando você tiver necessidades mais complexas de consulta, buscas, e análise de dados. Por exemplo, você pode usar o Amazon DynamoDB Streams para fazer upload de dados de streaming para o Amazon Elasticsearch Service. Algumas das vantagens do DynamoDB estão em seu recurso de escalonamento automático e em sua interface simples para armazenar dados. Outros incluem seus tempos de resposta rápidos para aplicativos exigentes com recursos como o Amazon DynamoDB Accelerator (DAX), e sua adaptação para arquiteturas sem servidor (serverless). Consultar e recuperar dados não precisa ser um problema se você analisar e planejar padrões de acesso de antemão, de acordo com suas necessidades.

 

Este artigo foi traduzido do Blog da AWS em Inglês.

 


Sobre el autor

AM Grobelny é Evangelista Técnico Sênior com foco em permitir que todos os tipos de desenvolvedores de software tenham sucesso na AWS.

 

 

 

 

Sobre los revisores

Carlos Robles é Arquiteto de Soluções especializado em base de dados na AWS.

 

 

 

 

 

Murilo Nascimento é Product Manager Sênior na AWS.

 

 

 

 

Explore mais conteúdos sobre Database na página de Sessions On Demand.

Acesse >