sql >> Base de Datos >  >> NoSQL >> MongoDB

Índices compuestos de MongoDB:¿importa el orden de clasificación?

Puede pensar en el índice de campo único de MongoDB como una matriz, con punteros a ubicaciones de documentos. Por ejemplo, si tiene una colección con (tenga en cuenta que la secuencia está desordenada deliberadamente):

[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

Ahora si lo haces:

db.collection.createIndex({a:1})

El índice se parece aproximadamente a:

[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1

Tenga en cuenta tres cosas importantes:

  • Está ordenado por a ascendente
  • Cada entrada apunta a la ubicación donde residen los documentos relevantes
  • El índice solo registra los valores de a campo. El b el campo no existe en absoluto en el índice

Así que si haces una consulta como:

db.collection.find().sort({a:1})

Todo lo que tiene que hacer es recorrer el índice de arriba a abajo, obteniendo y generando el documento al que apuntan las entradas. Tenga en cuenta que también puede recorrer el índice desde la parte inferior, por ejemplo:

db.collection.find().sort({a:-1})

y la única diferencia es que recorres el índice al revés.

Porque b no está en el índice en absoluto, no puede usar el índice al consultar algo sobre b .

Índice compuesto

En un índice compuesto, por ejemplo:

db.collection.createIndex({a:1, b:1})

Significa que desea ordenar por a primero, luego ordenar por b . El índice se vería así:

[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

Tenga en cuenta que:

  • El índice se ordena de a
  • Dentro de cada a tienes un b ordenado
  • Tiene 5 entradas de índice frente a solo tres en el ejemplo anterior de un solo campo

Usando este índice, puede hacer una consulta como:

db.collection.find({a:2}).sort({b:1})

Puede encontrar fácilmente donde a:2 luego camine el índice hacia adelante. Dado ese índice, no se puede :

db.collection.find().sort({b:1})
db.collection.find({b:1})

En ambas consultas no puede encontrar fácilmente b ya que está repartido por todo el índice (es decir, no en entradas contiguas). Sin embargo, puedes hacer:

db.collection.find({a:2}).sort({b:-1})

ya que esencialmente puedes encontrar dónde está el a:2 son, y caminan por el b entradas hacia atrás.

Editar :aclaración de la pregunta de @marcospgp en el comentario:

La posibilidad de utilizar el índice {a:1, b:1} para satisfacer find({a:2}).sort({b:-1}) en realidad tiene sentido si lo ve desde el punto de vista de una tabla ordenada. Por ejemplo, el índice {a:1, b:1} se puede considerar como:

a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

buscar({a:2}).ordenar({b:1})

El índice {a:1, b:1} significa sort by a, then within each a, sort the b values . Si luego haces find({a:2}).sort({b:1}) , el índice sabe dónde están todos los a=2 son. Dentro de este bloque de a=2 , el b se ordenaría en orden ascendente (según la especificación del índice), de modo que la consulta find({a:2}).sort({b:1}) puede ser satisfecho 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

buscar({a:2}).ordenar({b:-1})

Dado que el índice se puede caminar hacia adelante o hacia atrás, se siguió un procedimiento similar, con un pequeño giro al 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

El hecho de que el índice se pueda recorrer hacia adelante o hacia atrás es el punto clave que permite la consulta find({a:2}).sort({b:-1}) para poder usar el índice {a:1, b:1} .

Explicación del planificador de consultas

Puede ver lo que planea el planificador de consultas usando db.collection.explain().find(....) . Básicamente, si ves un stage de COLLSCAN , no se usó ni se puede usar ningún índice para la consulta. Ver explicar resultados para obtener detalles sobre la salida del comando.