Venho de um histórico de banco de dados relacional e estou tentando trabalhar com o DynamoDB do amazon
Eu tenho uma tabela com uma chave hash "DataID" e um intervalo "CreatedAt" e um monte de itens nela.
Estou tentando obter todos os itens que foram criados após uma data específica e classificados por data. O que é bastante simples em um banco de dados relacional.
No DynamoDB, a coisa mais próxima que consegui encontrar é uma consulta e usar a chave de intervalo maior que filtro. O único problema é que, para realizar uma consulta, preciso de uma chave hash que anula o propósito.
Então, o que estou fazendo de errado? Meu esquema de tabela está errado, a chave hash não deveria ser única? ou existe outra maneira de consultar?
fonte
CreatedAt
mais de um determinado ponto.Devido à sua estrutura de tabela atual, isso não é possível no DynamoDB. O grande desafio é entender que a chave Hash da tabela (partição) deve ser tratada como criação de tabelas separadas. Em alguns aspectos, isso é realmente poderoso (pense nas chaves de partição como a criação de uma nova tabela para cada usuário ou cliente, etc ...).
As consultas só podem ser feitas em uma única partição. Esse é realmente o fim da história. Isso significa que se você deseja consultar por data (você deseja usar mseg desde a época), todos os itens que deseja recuperar em uma única consulta devem ter o mesmo Hash (chave de partição).
Eu deveria qualificar isso. Você pode absolutamente
scan
pelo critério que está procurando, isso não é problema, mas isso significa que você estará olhando para cada linha em sua tabela e, em seguida, verificando se essa linha tem uma data que corresponda aos seus parâmetros. Isso é muito caro, especialmente se você estiver no negócio de armazenar eventos por data em primeiro lugar (ou seja, você tem muitas linhas).Você pode ficar tentado a colocar todos os dados em uma única partição para resolver o problema, e você pode com certeza, no entanto, sua taxa de transferência será dolorosamente baixa, visto que cada partição recebe apenas uma fração do valor total definido.
A melhor coisa a fazer é determinar partições mais úteis para criar para salvar os dados:
Você realmente precisa olhar todas as linhas ou são apenas as linhas de um usuário específico?
Seria normal primeiro restringir a lista por mês e fazer várias consultas (uma para cada mês)? Ou por ano?
Se você estiver fazendo uma análise de série temporal, existem algumas opções, altere a chave de partição para algo calculado
PUT
para tornarquery
mais fácil ou use outro produto aws como kinesis, que se presta apenas para adicionar log.fonte
yyyy
e hash sobre isso, mas também crie umacreated
data que você pode usar como sua chave de intervalo. Então você obtém 10 GB de dados por ano (27 MB por dia), o que provavelmente é adequado para mais circunstâncias. Significa que você precisa criar uma consulta por ano quando as consultas de data ultrapassam o limite do ano, mas pelo menos funcionará e é mais seguro do que criar uma chave hash fictícia.A abordagem que eu segui para resolver esse problema é criar um Índice Secundário Global conforme abaixo. Não tenho certeza se essa é a melhor abordagem, mas espero que seja útil para alguém.
Limitação imposta ao usuário da API HTTP para especificar o número de dias para recuperar dados, padronizado para 24 horas.
Dessa forma, sempre posso especificar o HashKey como o dia da data atual e o RangeKey pode usar os operadores> e <durante a recuperação. Dessa forma, os dados também são espalhados por vários fragmentos.
fonte
Sua chave Hash (primária do tipo) deve ser única (a menos que você tenha um intervalo como o declarado por outros).
No seu caso, para consultar sua tabela, você deve ter um índice secundário.
Sua chave Hash é o ID. Seu índice secundário é definido como: DataID-Created-index (esse é o nome que o DynamoDB usará)
Então, você pode fazer uma consulta como esta:
Basicamente, sua consulta é semelhante a:
O índice secundário aumentará as unidades de capacidade de leitura / gravação necessárias, portanto, você precisa considerar isso. Ainda é muito melhor do que fazer uma varredura, o que custará leituras e tempo (e é limitado a 100 itens, eu acredito).
Esta pode não ser a melhor maneira de fazer isso, mas para alguém acostumado com RD (também estou acostumado com SQL) é a maneira mais rápida de se tornar produtivo. Como não há restrições em relação ao esquema, você pode preparar algo que funcione e, uma vez que você tenha a largura de banda para trabalhar da maneira mais eficiente, pode mudar as coisas.
fonte
Você poderia transformar a chave Hash em algo semelhante a um id de 'categoria de produto' e, em seguida, a chave de intervalo como uma combinação de um carimbo de data / hora com um id exclusivo anexado no final. Dessa forma, você conhece a chave hash e ainda pode consultar a data com maior que.
fonte
Você pode ter várias chaves hash idênticas; mas apenas se você tiver uma chave de intervalo que varia. Pense nisso como formatos de arquivo; você pode ter 2 arquivos com o mesmo nome na mesma pasta, desde que seu formato seja diferente. Se o formato for o mesmo, o nome deve ser diferente. O mesmo conceito se aplica às chaves hash / range do DynamoDB; pense no hash como o nome e no intervalo como o formato.
Além disso, não me lembro se eles tinham na época do OP (não acredito que tivessem), mas agora eles oferecem índices secundários locais.
Meu entendimento disso é que agora deve permitir que você execute as consultas desejadas sem ter que fazer uma varredura completa. A desvantagem é que esses índices devem ser especificados na criação da tabela e também (eu acredito) não podem ficar em branco ao criar um item. Além disso, eles exigem taxa de transferência adicional (embora normalmente não tanto quanto uma varredura) e armazenamento, portanto, não é uma solução perfeita, mas uma alternativa viável para alguns.
Ainda assim, recomendo a resposta de Mike Brant como o método preferido de usar o DynamoDB; e uso esse método sozinho. No meu caso, tenho apenas uma tabela central com apenas uma chave hash como meu ID, depois as tabelas secundárias que têm um hash e um intervalo que podem ser consultados e o item aponta o código para o "item de interesse" da tabela central, diretamente .
Dados adicionais sobre os índices secundários podem ser encontrados na documentação do DynamoDB da Amazon aqui para os interessados.
De qualquer forma, espero que isso ajude qualquer pessoa que aconteça neste tópico.
fonte
Resposta atualizada Não há maneira conveniente de fazer isso usando consultas do Dynamo DB com taxa de transferência previsível. Uma opção (subótima) é usar um GSI com um HashKey & CreatedAt artificial. Em seguida, consulte apenas o HashKey e mencione ScanIndexForward para ordenar os resultados. Se você puder criar um HashKey natural (digamos, a categoria do item, etc.), esse método é o vencedor. Por outro lado, se você mantiver a mesma HashKey para todos os itens, isso afetará a taxa de transferência principalmente quando o conjunto de dados crescer além de 10 GB (uma partição)
Resposta original: Você pode fazer isso agora no DynamoDB usando GSI. Faça o campo "CreatedAt" como um GSI e emita consultas como (GT some_date). Armazene a data como um número (msegs desde a época) para esse tipo de consulta.
Os detalhes estão disponíveis aqui: Índices secundários globais - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using
Este é um recurso muito poderoso. Esteja ciente de que a consulta é limitada a (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Condição - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
fonte
CreatedAt
deveria ser a chave de intervalo do GSI, você precisará escolher uma chave hash - e então você está de volta ao ponto de partida, porque será capaz de consultar GTCreatedAt
apenas para um valor específico de chave de hash.