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 (aneste caso), umSORTna 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 umSORTna 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 porbdepois de satisfazer o parâmetro de igualdade ema. Por exemplo, para cadaa, existem muitosbque já estão ordenados porbdevido 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_MERGEstage 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 porbdevido 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.