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

Índices compostos do MongoDB - A ordem de classificação importa?


Você pode pensar no índice de campo único do MongoDB como uma matriz, com ponteiros para locais de documentos. Por exemplo, se você tiver uma coleção com (observe que a sequência está deliberadamente fora de ordem):
[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}

Índice de campo único


Agora se você fizer:
db.collection.createIndex({a:1})

O índice se parece aproximadamente com:
[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1

Observe três coisas importantes:
  • É classificado por a ascendente
  • Cada entrada aponta para o local onde residem os documentos relevantes
  • O índice registra apenas os valores do a campo. O b campo não existe no índice de forma alguma

Então, se você fizer uma consulta como:
db.collection.find().sort({a:1})

Tudo o que ele precisa fazer é percorrer o índice de cima para baixo, buscando e exibindo o documento apontado pelas entradas. Observe que você também pode percorrer o índice de baixo para cima, por exemplo:
db.collection.find().sort({a:-1})

e a única diferença é que você anda o índice ao contrário.

Porque b não está no índice, você não pode usar o índice ao consultar qualquer coisa sobre b .

Índice composto


Em um índice composto, por exemplo:
db.collection.createIndex({a:1, b:1})

Isso significa que você deseja classificar por a primeiro, depois classifique por b . O índice ficaria assim:
[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1

Observe que:
  • O índice é classificado de a
  • Em cada a você tem um b ordenado
  • Você tem 5 entradas de índice contra apenas três no exemplo anterior de campo único

Usando este índice, você pode fazer uma consulta como:
db.collection.find({a:2}).sort({b:1})

Ele pode encontrar facilmente onde a:2 em seguida, caminhe o índice para a frente. Dado esse índice, você não pode fazer :
db.collection.find().sort({b:1})
db.collection.find({b:1})

Em ambas as consultas, você não pode encontrar facilmente b uma vez que está espalhado por todo o índice (ou seja, não em entradas contíguas). No entanto, você pode Faz:
db.collection.find({a:2}).sort({b:-1})

já que você pode encontrar essencialmente onde o a:2 são, e percorra o b entradas para trás.

Editar :esclarecimento da pergunta do @marcospgp no comentário:

A possibilidade de usar o índice {a:1, b:1} para satisfazer find({a:2}).sort({b:-1}) realmente faz sentido se você vê-lo do ponto de vista de uma tabela classificada. Por exemplo, o índice {a:1, b:1} pode ser pensado como:
a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

localizar({a:2}).sort({b:1})

O índice {a:1, b:1} significa sort by a, then within each a, sort the b values . Se você fizer um find({a:2}).sort({b:1}) , o índice sabe onde estão todos os a=2 são. Dentro deste bloco de a=2 , o b seria classificada em ordem crescente (de acordo com a especificação do índice), de modo que a consulta find({a:2}).sort({b:1}) pode ser satisfeita por:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2

localizar({a:2}).sort({b:-1})

Como o índice pode ser andado para frente ou para trás, um procedimento semelhante foi seguido, com uma pequena torção no final:
a | b
--|--
1 | 1
1 | 2
2 | 1  <-- walk this block backward to satisfy
2 | 2  <-- find({a:2}).sort({b:-1})
2 | 3  <--
3 | 1
3 | 2

O fato de o índice poder avançar ou retroceder é o ponto chave que habilita a consulta find({a:2}).sort({b:-1}) para poder usar o índice {a:1, b:1} .

Explicação do planejador de consultas


Você pode ver o que o planejador de consultas planeja usando db.collection.explain().find(....) . Basicamente, se você vir um stage de COLLSCAN , nenhum índice foi usado ou pode ser usado para a consulta. Consulte explicar resultados para obter detalhes sobre a saída do comando.