Índices com hash
Os índices hash mantêm entradas com hashes dos valores do campo indexado.
Os índices com hash suportam fragmentação usando chaves de fragmento com hash. A fragmentação baseada em hash usa um índice em hash de um campo como chave de fragmentação para particionar dados em seu cluster fragmentado.
Usar uma chave de fragmento com hash para shard a collection resulta em uma distribuição mais uniforme de dados. Consulte Fragmentação em hash para obter mais detalhes.
Função de hash
Os índices hash usam uma função hash para calcular o hash do valor do campo de índice. [1] A função hash recolhe documentos incorporados e calcula o hash para todo o valor, mas não oferece suporte a várias chaves (ou seja matrizes) índices. Especificamente, criar um índice com hash em um campo que contém uma array ou tentar inserir uma array em um campo indexado com hash retorna um erro.
Dica
O MongoDB calcula automaticamente os hashes ao resolver consultas usando índices com hash. Os aplicativos não precisam calcular hashes.
[1] | A partir da versão 4.0, mongosh fornece o método convertShardKeyToHashed() . Esse método utiliza a mesma função de hash que o índice de hash e pode ser usado para ver qual seria o valor de hash para uma chave. |
Crie um índice com hash
Para criar um índice hashed, especifique hashed
como o valor da chave de índice, como no exemplo a seguir:
db.collection.createIndex( { _id: "hashed" } )
Criar um índice composto com hash
Novidades na versão 4.4.
A partir do MongoDB 4.4, o MongoDB suporta a criação de índices compostos que incluem um único campo hashed. Para criar um índice composto hasheado, especifique hashed
como valor para qualquer chave de índice única ao criá-lo:
db.collection.createIndex( { "fieldA" : 1, "fieldB" : "hashed", "fieldC" : -1 } )
Índices compostos com hash exigem FeatureCompatibilityVersion definido como 4.4
.
Considerações
Documentos incorporados
A função hash recolhe documentos incorporados e calcula o hash para todo o valor, mas não oferece suporte a várias chaves (ou seja, matrizes) índices. Especificamente, criar um índice com hash em um campo que contém uma array ou tentar inserir uma array em um campo indexado com hash retorna um erro.
Restrição única
O MongoDB não suporta a especificação de uma restrição única em um índice hashed
. Em vez disso, você pode criar um índice não hash adicional com a restrição exclusiva nesse campo. O MongoDB pode usar esse índice sem hash para impor a exclusividade no campo.
2 53 Limit
Aviso
Os índices hashed
do MongoDB truncam números de ponto flutuante em inteiros de 64 bits antes de fazer o hash. Por exemplo, um índice hashed
armazenaria o mesmo valor para um campo que tivesse valor de 2.3
, 2.2
e 2.9
. Para evitar colisões, não use um índice hashed
para números de ponto flutuante que não possam ser convertidos de forma confiável em inteiros de 64 bits (e, em seguida, de volta ao ponto flutuante). Os índices hashed
do MongoDB não suportam valores de ponto flutuante maiores que 2 53.
Para saber qual seria o valor hashed de uma chave, consulte convertShardKeyToHashed()
.
PowerPC and 2 63
Para índices de hash, o MongoDB 4.2 garante que o valor de hash para o valor de ponto flutuante 2 63 no PowerPC seja consistente com outras plataformas.
Embora os índices com hash em um campo que podem conter valores de ponto flutuante maiores que 2 53 sejam uma configuração sem suporte, os clientes ainda podem inserir documentos em que o campo indexado tem o valor 2 63.
Para listar todos os índices do hashed
para todas as coleções em seu sistema, você pode utilizar a seguinte operação em mongosh
:
db.adminCommand("listDatabases").databases.forEach(function(d){ let mdb = db.getSiblingDB(d.name); mdb.getCollectionInfos({ type: "collection" }).forEach(function(c){ let currentCollection = mdb.getCollection(c.name); currentCollection.getIndexes().forEach(function(idx){ let idxValues = Object.values(Object.assign({}, idx.key)); if (idxValues.includes("hashed")) { print("Hashed index: " + idx.name + " on " + d.name + "." + c.name); printjson(idx); }; }); }); });
Para verificar se o campo indexado contém o valor 2 63, execute a seguinte operação para a collection e o campo indexado:
Se o tipo de campo indexado for um escalar e nunca um documento:
// substitute the actual collection name for <collection> // substitute the actual indexed field name for <indexfield> db.<collection>.find( { <indexfield>: Math.pow(2,63) } ); Se o tipo de campo indexado for um documento (ou escalar), você poderá executar:
// substitute the actual collection name for <collection> // substitute the actual indexed field name for <indexfield> db.<collection>.find({ $where: function() { function findVal(obj, val) { if (obj === val) return true; for (const child in obj) { if (findVal(obj[child], val)) { return true; } } return false; } return findVal(this.<indexfield>, Math.pow(2, 63)); } })