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 parasort({b:1,c:1})
ousort({b:-1,c:-1})
mas nãosort({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
-
O MongoDB usa apenas um índice para a maioria das consultas. Por exemplo, para evitar umSORT
na memória estágio na consulta
db.a.find({a:1}).sort({b:1})
o índice deve cobrir tantoa
eb
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.
-
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:ofind()
seguido porsort()
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 é:
- MinKey (tipo interno)
- Nulo
- Números (ints, longs, doubles, decimals)
- Símbolo, string
- Objeto
- Matriz
- BinData
- ObjectID
- Booleano
- Data
- Carimbo de data e hora
- Expressão regular
- 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.