Observação: Esta resposta é baseada no MongoDB 3.2.4.
Vale a pena descobrir o uso de
explain()
no MongoDB. O explain()
saída de uma consulta (por exemplo, db.collection.explain().find(...)
) permite verificar qual índice é usado em uma consulta e usar db.collection.explain('executionStats')
também mostrará se a consulta foi bem-sucedida ou falhou devido a SORT
na memória limitação. $in
Um
$in
pode ser considerada como uma série de consultas de igualdade. Por exemplo, {a: {$in: [1,3,5]}}
poderia ser considerado como {a:1}, {a:3}, {a:5}
. O MongoDB classificará o $in
array antes de prosseguir com a consulta, para que {$in: [3,5,1]}
não é diferente de {$in: [1,3,5]}
. Vamos supor que a coleção tenha um índice de
{a:1, b:1}
-
Classificando pora
db.coll.find({a: {$in: [1,3,5]}}).sort({a:1})
O MongoDB poderá usar o{a:1,b:1}
index, pois essa consulta pode ser considerada uma união de{a:1}, {a:3}, {a:5}
consultas. Classificando por{a:1}
permite o uso de prefixo de índice , portanto, o MongoDB não precisa executar uma classificação na memória.
A mesma situação também se aplica à consulta:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})
desdesort({a:1})
também usa o prefixo de índice (a
neste caso), umSORT
na memória estágio, portanto, não é necessário.
-
Classificando porb
Este é um caso mais interessante comparado à classificação pora
. Por exemplo:
db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})
Aexplain()
a saída desta consulta terá um estágio chamadoSORT_MERGE
. Lembre-se que ofind()
parte da consulta pode ser considerada como{a:1}, {a:3}, {a:5}
.
A consultadb.coll.find({a:1}).sort({b:1})
não precisa ter umSORT
na memória estágio devido à natureza do{a:1,b:1}
index:ou seja, o MongoDB pode simplesmente percorrer o índice (classificado) e retornar documentos classificados porb
depois de satisfazer o parâmetro de igualdade ema
. Por exemplo, para cadaa
, existem muitosb
que já estão ordenados porb
devido ao índice.
Usando$in
, a consulta geral pode ser considerada como:
db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Pegue os resultados individuais da consulta acima e faça uma mesclagem usando o valor de
b
. A consulta não precisa de um estágio de classificação na memória porque os resultados da consulta individual já estão classificados porb
. O MongoDB só precisa mesclar os resultados da subconsulta (já classificados) em um único resultado.
Da mesma forma, a consulta
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})
também usa umSORT_MERGE
stage e é muito semelhante à consulta acima. A diferença é que as consultas individuais produzem documentos com base em um intervalo deb
(em vez de todosb
) para cadaa
(que será ordenado porb
devido ao índice{a:1,b:1}
). Portanto, a consulta não precisa de um estágio de classificação na memória.
$ou
Para um
$or
query para usar um índice, todas as cláusulas no $or
expressão deve ter um índice associado a ela
. Se este requisito for atendido, é possível que a consulta empregue um SORT_MERGE
stage como um $in
consulta. Por exemplo:db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
terá um plano de consulta quase idêntico, uso de índice e
SORT_MERGE
estágio como no $in
exemplo acima. Essencialmente, a consulta pode ser pensada como:db.coll.find({a:1}).sort({b:1})
db.coll.find({a:3}).sort({b:1})
db.coll.find({a:5}).sort({b:1})
- Pegue os resultados individuais da consulta acima e faça uma mesclagem usando o valor de
b
.
assim como o
$in
exemplo antes. No entanto, esta consulta:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
não pode usar nenhum índice (já que não temos o
{b:1}
índice). Essa consulta resultará em uma verificação de coleção e, consequentemente, terá um estágio de classificação na memória uma vez que nenhum índice é usado. Se, no entanto, criarmos o índice
{b:1}
, a consulta prosseguirá assim:db.coll.find({a:1}).sort({b:1})
db.coll.find({b:1}).sort({b:1})
- Pegue os resultados individuais da consulta acima e faça uma mesclagem usando o valor de
b
(que já está ordenado em ambas as subconsultas, devido aos índices{a:1,b:1}
e{b:1}
).
e o MongoDB combinará os resultados de
{a:1}
e {b:1}
consultas e realizar uma mesclagem nos resultados. O processo de fusão é em tempo linear, e. O(n)
. Em conclusão, em um
$or
consulta, cada termo deve ter um índice, incluindo o sort()
palco. Caso contrário, o MongoDB terá que realizar uma classificação na memória.