Diferença entre índices locais e globais no DynamoDB

128

Estou curioso sobre esses dois índices secundários e as diferenças entre eles. É difícil imaginar como isso se parece. E eu acho que isso ajudará mais pessoas do que apenas eu.

Michael Czolko
fonte
1
Respondida nas Perguntas frequentes do DynamoDB . Procure por "Como os índices secundários globais diferem dos índices secundários locais?"
Markdsievers #
1
Não é tão fácil de encontrar a partir do FAQ agora. Talvez seja reorganizada
binithb

Respostas:

114

Os índices secundários locais ainda dependem da chave hash original. Ao fornecer uma tabela com hash + range, pense no LSI como hash + range1, hash + range2 .. hash + range6. Você recebe mais 5 atributos de intervalo para consulta. Além disso, existe apenas uma taxa de transferência provisionada.

Os índices secundários globais definem um novo paradigma - diferentes chaves de hash / intervalo por índice.
Isso interrompe o uso original de uma chave de hash por tabela. É também por isso que, ao definir o GSI, é necessário adicionar um rendimento provisionado por índice e pagar por ele.

Informações mais detalhadas sobre as diferenças podem ser encontradas no anúncio do GSI

Chen Harel
fonte
2
Pode querer adicionar 1) índices secundários, sejam LSI ou GSI, não tendo nada a ver com exclusividade
user1322092
1
Você tem permissão para ter até 5 índices secundários locais, é por isso que Chen Harel diz "Você recebe mais 5 atributos de intervalo para consulta" .
Felipe Alvarez
93

Aqui está a definição formal da documentação:

Índice secundário global - um índice com uma chave de hash e intervalo que pode ser diferente da tabela. Um índice secundário global é considerado "global" porque as consultas no índice podem abranger todos os dados em uma tabela, em todas as partições.

Índice secundário local - um índice que possui a mesma chave de hash da tabela, mas uma chave de intervalo diferente. Um índice secundário local é "local" no sentido de que todas as partições de um índice secundário local têm o escopo definido para uma partição de tabela que possui a mesma chave de hash.

No entanto, as diferenças vão muito além das possibilidades em termos de definições-chave. Abaixo, alguns fatores importantes que impactarão diretamente o custo e o esforço para manter os índices:

  • Taxa de transferência :

Os índices secundários locais consomem a taxa de transferência da tabela. Quando você consulta registros por meio do índice local, a operação consome unidades de capacidade de leitura da tabela. Quando você executa uma operação de gravação (criar, atualizar, excluir) em uma tabela que possui um índice local, haverá duas operações de gravação, uma para a tabela e outra para o índice. Ambas as operações consumirão unidades de capacidade de gravação da tabela.

Os índices secundários globais têm sua própria taxa de transferência provisionada; quando você consulta o índice, a operação consome capacidade de leitura do índice; quando você executa uma operação de gravação (criar, atualizar, excluir) em uma tabela que possui um índice global, haverá dois operações de gravação, uma para a tabela e outra para o índice *.

* Ao definir a taxa de transferência provisionada para o Índice Secundário Global, preste atenção especial aos seguintes requisitos:

Para que uma gravação de tabela seja bem-sucedida, as configurações de taxa de transferência provisionada para a tabela e todos os seus índices secundários globais devem ter capacidade de gravação suficiente para acomodar a gravação; caso contrário, a gravação na tabela será regulada.

  • Gestão :

Os índices secundários locais só podem ser criados quando você está criando a tabela; não há como adicionar o índice secundário local a uma tabela existente; também, depois de criar o índice, você não pode excluí-lo.

Os índices secundários globais podem ser criados quando você cria a tabela e é adicionado a uma tabela existente, a exclusão de um índice secundário global existente também é permitida.

  • Consistência de leitura:

Os índices secundários locais suportam consistência eventual ou forte, enquanto o índice secundário global suporta apenas consistência eventual.

  • Projeção:

Os índices secundários locais permitem recuperar atributos que não são projetados para o índice (embora com custo adicional: desempenho e unidades de capacidade consumida). Com o Índice Secundário Global, você pode recuperar apenas os atributos projetados no índice.

Consideração especial sobre a exclusividade das chaves definidas para índices secundários:

Em um Índice Secundário Local, o valor da chave do intervalo NÃO precisa ser exclusivo para um determinado valor da chave de hash, o mesmo se aplica aos Índices Secundários Globais, os valores da chave (Hash e Intervalo) NÃO precisam ser exclusivos.

Fonte: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html

bsd
fonte
1
" Os índices secundários globais têm sua própria taxa de transferência provisionada; quando você consulta o índice, a operação consome capacidade de leitura da tabela " - Errado. As consultas ou varreduras em um índice secundário global consomem unidades de capacidade do índice, não da tabela base.
ethanxyz_0 8/08/17
1
@bsd Faria sentido adicionar uma observação sobre uma das principais limitações impostas pelo uso de LSI: "Para tabelas com índices secundários locais, há um limite de tamanho de 10 GB por valor da chave de partição. Uma tabela com índices secundários locais pode armazenar qualquer número de itens, desde que o tamanho total de qualquer valor de chave de partição não exceda 10 GB ". ( docs.aws.amazon.com/amazondynamodb/latest/developerguide/… )
wvdz 16/05/19
29

Estas são as possíveis pesquisas por índice:

  • Por Hash
  • Por Hash + Range
  • Por Hash + Índice local
  • Por índice global
  • Por índice global + índice de intervalo

Índices Hash e Range de uma tabela: estes são os índices habituais das versões anteriores do Amazon AWS SDK.

Índices globais e locais: são índices 'adicionais' criados em uma tabela, além dos índices de hash e intervalo existentes da tabela. O índice global é semelhante a um hash. O índice de intervalo se comporta de maneira semelhante ao índice de intervalo usado com o hash da tabela. No seu modelo de entidade em seu código, o getter deve ser anotado desta maneira:

  • Para índices globais:

    @DynamoDBIndexHashKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
    @DynamoDBAttribute(attributeName = PROPERTY_USER)
    public String getUser() {
        return user;
    }
    
  • Para o índice de intervalo associado ao índice global:

    @DynamoDBIndexRangeKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
    @DynamoDBAttribute(attributeName = PROPERTY_TIMESTAMP)
    public String getTimestamp() {
        return timestamp;
    }
    

Além disso, se você ler uma tabela por um índice Global, ela deverá ser uma leitura Eventual (não leitura consistente):

queryExpression.setConsistentRead(false);
Carlos AG
fonte
20

Uma maneira de colocar isso é o seguinte:

LSI - permite executar uma consulta em uma única Hash-Key enquanto usa vários atributos diferentes para "filtrar" ou restringir a consulta.

GSI - permite executar consultas em várias chaves de hash em uma tabela, mas, como resultado, resulta em custos adicionais na taxa de transferência.

Uma análise mais abrangente dos tipos de tabela e como eles funcionam, abaixo:

Apenas hash

Como você provavelmente já sabe; uma Hash-Key por si só deve ser exclusiva, pois a gravação em uma Hash-Key que já existe substituirá os dados existentes.

Hash + Range

Uma Hash-Key + Range-Key permite que você tenha várias teclas Hash iguais, desde que tenham uma tecla de intervalo diferente. Nesse caso, se você gravar em uma Hash-Key que já existe, mas usar uma Range-Key que ainda não é usada por essa Hash-Key, ela criará um novo item, enquanto que se um item com a mesma combinação Hash + Range já existe, substitui o item correspondente.

Outra maneira de pensar sobre isso é como um arquivo com um formato. Você pode ter um arquivo com o mesmo nome (hash) que outro, na mesma pasta (tabela), desde que o formato (intervalo) seja diferente. Da mesma forma, você pode ter vários arquivos do mesmo formato, desde que o nome seja diferente.

LSI

Um LSI é basicamente o mesmo que Hash-Key + Range-Key e segue as mesmas regras que ele, ao criar itens, exceto que você também deve fornecer valores para os LSIs; eles não podem ser deixados vazios / nulos.

Dizer que um LSI é "Range-Key 2" não está totalmente correto, pois você não pode ter (usando meu arquivo e formatar a analogia anteriormente) um arquivo chamado: file.format.lsie file.format.lsi2. Você pode, no entanto, ter file.format.lsie file.format2.lsiou file.format.lsie file2.format.lsi.

Basicamente, um LSI é apenas uma "chave de filtro", não uma chave de intervalo real; sua combinação básica de valores Hash e Intervalo ainda deve ser única, enquanto os valores LSI não precisam ser únicos. Uma maneira mais fácil de ver isso é pensar no LSI como dados nos arquivos. Você pode escrever um código que encontre todos os arquivos com o nome "PROJECT101", independentemente deles fileFormat, e depois leia os dados para determinar o que deve ser incluído na consulta e o que é omitido. É basicamente assim que o LSI funciona (apenas sem a sobrecarga extra de abrir o arquivo para ler seu conteúdo).

GSI

Para o GSI, você está essencialmente criando outra tabela para cada GSI, mas sem o incômodo de manter várias tabelas separadas que espelham dados entre eles; é por isso que eles custam mais rendimento.

Portanto, para um GSI, você pode especificar fileNamecomo Hash-Key fileFormatbase e como Range-Key base. Em seguida, você pode especificar um GSI que possua uma Hash-Key fileName2e uma Range-Key of fileFormat2. Você pode consultar em um fileNameoufileName2 se quiser, ao contrário do LSI, onde você pode apenas consultar fileName.

As principais vantagens são que você só precisa manter uma tabela, em vez de 2, e sempre que gravar no Hash / Range primário ou no GSI Hash / Range (s), os outros também serão atualizados automaticamente, então você não pode "esquecer" de atualizar as outras tabelas como você pode com uma configuração de várias tabelas. Além disso, não há chance de uma conexão perdida após a atualização de uma e antes da atualização da outra, como ocorre na configuração de várias tabelas.

Além disso, um GSI pode "sobrepor" a combinação básica Hash / Range. Então, se você quiser fazer uma mesa com fileNamee fileFormatcomo base Hash / Range filePriorityefileName como seu GSI, você pode.

Por fim, uma combinação GSI Hash + Range não precisa ser única, enquanto a combinação base Hash + Range precisa ser única. Isso é algo que não é possível com uma configuração de mesa dupla / múltipla, mas é com GSI. Como resultado, você DEVE fornecer valores para a base e o GSI Hash + Range, ao atualizar; nenhum desses valores pode ser vazio / nulo.

DGolberg
fonte
13

Outra maneira de explicar: o LSI ajuda você a fazer consultas adicionais sobre itens com a mesma chave Hash. O GSI ajuda você a fazer consultas semelhantes nos itens "do outro lado da mesa". Tão muito útil.

Se você possui uma tabela de perfil de usuário: ID exclusivo, nome, email. Aqui, se você precisar tornar a tabela consultável em nome, email - a única maneira é torná-las GSI (o LSI não ajudará)

Sony Kadavan
fonte
1

Esta documentação fornece uma boa explicação:

https://aws.amazon.com/blogs/aws/now-available-global-secondary-indexes-for-amazon-dynamodb/

Não pude comentar esta questão, mas qual é melhor em termos de desempenho de gravação e leitura:

(Índice local com taxa de transferência de leitura e gravação de tabela de 100) ou (Índice global com taxa de transferência de leitura / gravação de 50 junto com taxa de transferência de leitura / gravação de tabela de 50?)

Não preciso de chave de partição separada para o meu caso de uso, portanto, o índice local deve ser suficiente para a funcionalidade necessária.

Sindhu
fonte
0

GSIs não podem ser usados ​​para leituras consistentes.

Os LSIs podem ser usados ​​para leituras consistentes, mas limitarão o tamanho da partição principal a 10 GB. Também os LSIs podem ser criados apenas na criação da tabela.

david_adler
fonte