MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Índice de Composto Triplo Mongo


linha de fundo / tl;dr: Índice b pode ser 'ignorado' se a e c são consultados para igualdade ou desigualdade, mas não, por exemplo, para ordenações em c .

Esta é uma pergunta muito boa. Infelizmente, não consegui encontrar nada que responda com autoridade a isso com mais detalhes. Acredito que o desempenho dessas consultas melhorou nos últimos anos, então não confiaria em material antigo sobre o assunto.

A coisa toda é bastante complicada porque depende da seletividade em seus índices e se você consulta por igualdade, desigualdade e/ou classificação, então explain() é seu único amigo, mas aqui estão algumas coisas que encontrei:

Advertência :O que vem agora é uma mistura de resultados experimentais, raciocínio e adivinhação. Eu posso estar levando a analogia de Kyle longe demais, e eu posso até estar completamente errado (e azar, porque os resultados dos meus testes correspondem vagamente ao meu raciocínio).

É claro que o índice de A pode ser usado, o que, dependendo da seletividade de A, certamente é muito útil. 'Skipping' B pode ser complicado, ou não. Vamos manter isso semelhante ao exemplo do livro de receitas de Kyle:
French
    Beef
        ...
    Chicken
        Coq au Vin
        Roasted Chicken
    Lamb
        ...
    ...

Se agora você me pedir para encontrar algum prato francês chamado "Chateaubriand", posso usar o índice A e, por não conhecer o ingrediente, terei que escanear todos os pratos em A . Por outro lado, sei que a lista de pratos em cada categoria é classificada através do índice C , então só terei que procurar as strings começando com, digamos, "Cha" em cada lista de ingredientes. Se houver 50 ingredientes, precisarei de 50 pesquisas em vez de apenas uma, mas isso é muito melhor do que ter que escanear todos os pratos franceses!

Em meus experimentos, o número era muito menor que o número de valores distintos em b :nunca pareceu exceder 2. No entanto, testei isso apenas com uma única coleção e provavelmente tem a ver com a seletividade do b -índice.

Se você me pedir para lhe dar uma lista ordenada alfabeticamente de todos os pratos franceses , no entanto, eu teria problemas . Agora o índice em C é inútil, eu teria que ordenar por mesclagem todas essas listas de índice. Vou ter que escanear cada elemento para fazer isso.

Isso reflete nos meus testes. Aqui estão alguns resultados simplificados. A coleção original tem datetimes, ints e strings, mas eu queria manter as coisas simples, então agora é tudo ints.

Essencialmente, existem apenas duas classes de consultas:aquelas em que nscanned <=2 * limit , e aqueles que precisam digitalizar toda a coleção (120 mil documentos). O índice é {a, b, c} :
// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1}); 

// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});

// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});

Sua milhagem irá variar.