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

Como a classificação com um índice funciona no MongoDB?


Os índices no MongoDB são armazenados em uma estrutura de árvore B, onde cada entrada de índice aponta para um local específico no disco. Usar uma estrutura de árvore B também significa que um índice do MongoDB é armazenado em uma ordem classificada, sempre percorrido em ordem, e é barato para o MongoDB buscar uma série de documentos em uma ordem classificada por meio de índices.

Atualizar :A estrutura de árvore B é verdadeira para o mecanismo de armazenamento MMAPv1, mas é implementada de forma ligeiramente diferente pelo mecanismo de armazenamento WiredTiger (padrão desde o MongoDB 3.2). A ideia básica permanece a mesma, onde é barato percorrer o índice em uma ordem ordenada.

Um SORT estágio (ou seja, classificação na memória) em uma consulta é limitado a 32 MB de uso de memória. Uma consulta falhará se o SORT estágio excede esse limite. Esse limite pode ser contornado utilizando a natureza ordenada dos índices, para que o MongoDB possa retornar uma consulta com um sort() parâmetro sem executar uma classificação na memória.

Vamos supor que a consulta tenha a forma:
    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort(...)

com a coleção a tendo um índice de:
    db.a.createIndex({b:1,c:1})

Existem dois cenários possíveis quando um sort() stage é especificado na consulta:

1. O MongoDB não pode usar a natureza classificada do índice e deve executar um SORT na memória estágio .

Este é o resultado se a consulta não puder usar o "prefixo de índice". Por exemplo:
    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({c:1})

Na consulta acima, o índice {b:1,c:1} pode ser usado para:
  • Corresponder a documentos com b maior que 100 para o {b:{$gt:100}} parte da consulta.
  • No entanto, não há garantia de que os documentos devolvidos sejam classificados de acordo com c .

Portanto, o MongoDB não tem escolha a não ser executar uma classificação na memória. A explain() a saída desta consulta terá um SORT etapa. Este SORT estágio seria limitado a 32 MB de uso de memória.

2. O MongoDB pode usar a natureza classificada do índice .

Este é o resultado se a consulta usar:
  • Classifique as chaves que correspondem à ordem do índice e
  • Especifica a mesma ordem do índice (ou seja, o índice {b:1,c:1} pode ser usado para sort({b:1,c:1}) ou sort({b:-1,c:-1}) mas não sort({b:1,c:-1}) )

Por exemplo:
    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({b:1})

Na consulta acima, o índice {b:1,c:1} pode ser usado para:
  • Corresponder a documentos com b maior que 100 para o {b:{$gt:100}} parte da consulta.
  • Neste caso, MongoDB pode garantir que os documentos retornados sejam classificados em termos de b .

A explain() a saída da consulta acima não tem um SORT etapa. Além disso, o explain() saída da consulta com e sem sort() são idênticos . Em essência, estamos obtendo o sort() de graça.

Um recurso valioso para entender esse assunto é Otimizando índices compostos do MongoDB. Observe que esta postagem de blog foi escrita em 2012. Embora parte da terminologia possa estar desatualizada, o tecnicismo da postagem ainda é relevante.

Atualização sobre perguntas de acompanhamento

  1. O MongoDB usa apenas um índice para a maioria das consultas. Por exemplo, para evitar um SORT na memória estágio na consulta
    db.a.find({a:1}).sort({b:1})
    

    o índice deve cobrir tanto a e b campos ao mesmo tempo; por exemplo. um índice composto como {a:1,b:1} É necessário. Você não pode ter dois índices separados {a:1} e {b:1} , e espere o {a:1} índice a ser usado para a parte de igualdade e o {b:1} índice a ser usado para a parte de classificação. Nesse caso, o MongoDB escolherá um dos dois índices.

    Portanto, é correto que os resultados sejam classificados porque são pesquisados ​​e retornados na ordem do índice.

  2. Para evitar uma classificação na memória usando um índice composto, a primeira parte do índice deve atender à parte de igualdade da consulta, e a segunda parte deve atender à parte de classificação da consulta (como mostrado na explicação para (1) acima).

    Se você tiver uma consulta como esta:
    db.a.find({}).sort({a:1})
    

    o índice {a:1,b:1} pode ser usado para a parte de classificação (já que você está basicamente retornando a coleção inteira). E se sua consulta for assim:
    db.a.find({a:1}).sort({b:1})
    

    o mesmo índice {a:1,b:1} também pode ser usado para ambas as partes da consulta. Também:
    db.a.find({a:1,b:1})
    

    também pode usar o mesmo índice {a:1,b:1}

    Observe o padrão aqui:o find() seguido por sort() os parâmetros seguem a ordem do índice {a:1,b:1} . Portanto, um índice composto deve ser ordenado por igualdade -> classificação .

Atualização sobre a classificação de diferentes tipos

Se um campo tiver tipos diferentes entre documentos (por exemplo, se a é string em um documento, número em outros, booleano em outro), como a classificação procede?

A resposta é a ordem de comparação do tipo MongoDB BSON. Para parafrasear a página de manual, a ordem é:
  1. MinKey (tipo interno)
  2. Nulo
  3. Números (ints, longs, doubles, decimals)
  4. Símbolo, string
  5. Objeto
  6. Matriz
  7. BinData
  8. ObjectID
  9. Booleano
  10. Data
  11. Carimbo de data e hora
  12. Expressão regular
  13. MaxKey (tipo interno)

Assim, a partir do exemplo acima, usando ordem crescente, os documentos contendo números aparecerão primeiro, depois strings e depois booleanos.