¿Por qué importa la dirección del índice en MongoDB?

114

Para citar los documentos :

Al crear un índice, el número asociado con una clave especifica la dirección del índice, por lo que siempre debe ser 1 (ascendente) o -1 (descendente). La dirección no importa para los índices de clave única o para la recuperación de acceso aleatorio, pero es importante si está haciendo ordenaciones o consultas de rango en índices compuestos.

Sin embargo, no veo ninguna razón por la que la dirección del índice deba importar en los índices compuestos. ¿Alguien puede proporcionar una explicación más detallada (o un ejemplo)?

johndodo
fuente

Respuestas:

112

MongoDB concatena la clave compuesta de alguna manera y la usa como clave en un BTree.

Al buscar elementos individuales : el orden de los nodos en el árbol es irrelevante.

Si está devolviendo un rango de nodos , los elementos cercanos entre sí estarán en las mismas ramas del árbol. Cuanto más cerca estén los nodos del rango, más rápido se podrán recuperar.

Con un solo índice de campo : el orden no importará. Si están juntas en orden ascendente, también estarán juntas en orden descendente.

Cuando tienes una clave compuesta , el orden comienza a importar.

Por ejemplo, si la clave es A ascendente B ascendente, el índice podría verse así:

Fila AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

Una consulta para A ascendente B descendente necesitará saltar alrededor del índice fuera de orden para devolver las filas y será más lenta. Por ejemplo, devolverá Row1, 3, 2, 6, 5, 4, 7

Una consulta de rango en el mismo orden que el índice simplemente devolverá las filas secuencialmente en el orden correcto.

Encontrar un registro en un BTree toma O (Log (n)) tiempo. Encontrar un rango de registros en orden es solo OLog (n) + k donde k es el número de registros a devolver.

Si los registros están fuera de orden, el costo podría ser tan alto como OLog (n) * k

Jared Kells
fuente
1
La fila resultante probablemente debería ser 1, 3, 2, 6, 5, 4, 7?
johndodo
Todavía no veo ninguna razón para que sea más lento. Solo el algoritmo debería ser diferente (para cada grupo de valores en A debería saltar al final del grupo y procesarlo en orden inverso), pero como los índices de MongoDB están en la memoria, no deberían tener un efecto notable en la velocidad. Además, RDBMS no sabe nada sobre la dirección con índices y la situación es bastante similar afaik?
johndodo
8
La razón por la que es un éxito en el rendimiento es porque no es solo una lista secuencial en la memoria como el ejemplo simplificado. En realidad, es un árbol ponderado. Saltar fuera de orden implicará atravesar el árbol nuevamente. Los RDMS definitivamente tienen orden en los índices.
Jared Kells
1
Obtener nodos de un BTree en orden es tan simple como moverse a lo largo de cada hoja hasta que se agote y luego subir un nivel y bajar la siguiente rama. Está O (n) Fuera de servicio, consume mucho más CPU.
Jared Kells
Gracias por una mayor aclaración. Revisé los documentos para los índices de MySQL ; realmente es posible especificar la dirección del índice, pero la configuración se ignora.
johndodo
45

La respuesta simple que está buscando es que la dirección solo importa cuando está ordenando en dos o más campos .

Si está ordenando por {a : 1, b : -1}:

El índice {a : 1, b : 1}será más lento que el índice{a : 1, b : -1}

Zaid Masud
fuente
1
@MarkPieszak porque toda la clasificación tendría que hacerse en la memoria, haciendo que el índice sea inútil
Sammaye
@Sammaye Creo que esa es la idea correcta, aunque no estoy seguro de que sea todo el tipo. Tendría que mirar en la puesta en práctica de saber cómo funciona realmente, pero yo creo que los resultados podrían ser tirado hacia atrás ordenados por una sola, y luego el adicional de B tendría que ser hecho en memoria de clasificación.
Zaid Masud
1
hmm, extraño la última vez que verifiqué el código, se eliminó la clasificación parcial debido a cómo estaba la clasificación, pero meh, tal vez haya cambiado
Sammaye
¿Qué pasa si estoy clasificando {a: -1, b: -1}, debería tener {a: -1, b: -1}índice o será {a: 1, b: 1}suficiente?
Hussain
@Hussain en su ejemplo, el {a: 1, b: 1}índice debería ser suficiente, ya que invertir un índice por completo está bien. Por ejemplo, Index on {a: 1}se puede usar para ordenar en{a: -1}
Zaid Masud
12

Por que los índices

Comprende dos puntos clave.

  1. Si bien un índice es mejor que ningún índice, el índice correcto es mucho mejor que cualquiera de los dos.
  2. MongoDB solo usará un índice por consulta, creando índices compuestos con el orden de campo adecuado para lo que probablemente desee usar.

Los índices no son gratuitos. Toman memoria e imponen una penalización de rendimiento al realizar inserciones, actualizaciones y eliminaciones. Normalmente, el impacto en el rendimiento es insignificante (especialmente en comparación con las ganancias en el rendimiento de lectura), pero eso no significa que no podamos ser inteligentes al crear nuestros índices.

Cómo los índices

Identificar qué grupo de campos deben indexarse ​​juntos se trata de comprender las consultas que está ejecutando. El orden de los campos utilizados para crear su índice es fundamental. La buena noticia es que, si obtiene un orden incorrecto, el índice no se usará en absoluto, por lo que será fácil de detectar con una explicación.

Por qué ordenar

Es posible que sus consultas deban ordenar. Pero ordenar puede ser una operación costosa, por lo que es importante tratar los campos en los que está ordenando como si fueran un campo que está consultando. Entonces será más rápido si tiene index. Sin embargo, hay una diferencia importante, el campo que está ordenando debe ser el último campo en su índice. La única excepción a esta regla es que si el campo también forma parte de su consulta, la regla debe ser la última no se aplica.

Cómo ordenar

Puede especificar un orden en todas las claves del índice o en un subconjunto; sin embargo, las claves de clasificación deben aparecer en el mismo orden en que aparecen en el índice. Por ejemplo, un patrón de clave de índice {a: 1, b: 1} puede admitir una ordenación en {a: 1, b: 1} pero no en {b: 1, a: 1}.

La clasificación debe especificar la misma dirección de clasificación (es decir, ascendente / descendente) para todas sus claves como patrón de clave de índice o especificar la dirección de clasificación inversa para todas sus claves como patrón de clave de índice. Por ejemplo, un patrón de clave de índice {a: 1, b: 1} puede admitir una ordenación en {a: 1, b: 1} y {a: -1, b: -1} pero no en {a: -1 , b: 1}.

Supongamos que existen estos índices:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Example                                                    Index Used
db.data.find().sort( { a: 1 } )                            { a: 1 }
db.data.find().sort( { a: -1 } )                           { a: 1 }
db.data.find().sort( { a: 1, b: 1 } )                      { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } )                    { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } )                { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )   { a: 1, b: 1 }
Somnath Muluk
fuente
Entiendo que es un ejemplo, pero si hay un índice de { a: 1, b: 1, c: 1 }lo que realmente necesita índices { a: 1}y { a: 1, b: 1}o índice { a: 1, b: 1, c: 1 }abarca todos los casos? Si las consultas siempre usan el mismo orden: 1 no ordena en la consulta con -1
Lukas Liesis
1
Si hay muchas consultas que funcionan solo en la propiedad 'a', es más rápido buscar con el índice con la propiedad 'a' para el motor de base de datos, que buscar por índice con 3 propiedades 'a', 'b', 'c'. Porque el tamaño del índice aumentará y la cuenta también aumentará. ex. Si hay 20 capítulos en el libro. Así que es más rápido ir al capítulo 3 y luego a la página específica. @LukasLiesis
Somnath Muluk