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

MongoDb:cómo crear el índice correcto (compuesto) para datos con muchos campos de búsqueda

Trataré de explicar qué significa esto con un ejemplo. Los índices basados ​​​​en B-tree no son algo específico de mongodb. Por el contrario, es un concepto bastante común.

Entonces, cuando crea un índice, le muestra a la base de datos una forma más fácil de encontrar algo. Pero este índice se almacena en algún lugar con un puntero que apunta a una ubicación del documento original. Esta información está ordenada y podrías verla como un árbol binario que tiene una propiedad muy buena:la búsqueda se reduce de O(n) (escaneo lineal) a O(log(n)) . Lo cual es mucho más rápido porque cada vez recortamos nuestro espacio a la mitad (potencialmente podemos reducir el tiempo de 10^6 a 20 búsquedas). Por ejemplo, tenemos una gran colección con el campo {a : some int, b: 'some other things'} y si lo indexamos por a, terminamos con otra estructura de datos que está ordenada por a . Se ve de esta manera (con esto no quiero decir que sea otra colección, esto es solo para demostración):

{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field

Así que ahora estamos buscando un campo a =18. En lugar de ir uno por uno a través de todos los elementos, tomamos algo en el medio y si es más grande que 18, dividimos la parte inferior por la mitad y verificamos el elemento allí. . Continuamos hasta que encontremos a =18. Luego miramos el puntero y al saberlo extraemos el campo original.

La situación con el índice compuesto es similar (en lugar de ordenar por un elemento, ordenamos por muchos). Por ejemplo, tienes una colección:

{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' }  // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' }  // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' }  // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' }  // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' }  // position 7 on the disk

y quiero un índice { "artículo":1, "ubicación":1, "stock":1}. La tabla de búsqueda se vería así (una vez más, esta no es otra colección, es solo una demostración):

{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }

Vea que aquí todo está básicamente ordenado por elemento, luego por ubicación y luego por puntero. De la misma manera que con un solo índice, no necesitamos escanear todo. Si tenemos una consulta que busca item = 2, location = 5 and stock = 7 podemos identificar rápidamente dónde están los documentos con item = 2 son y luego de la misma manera rápidamente identifique dónde entre estos elementos elemento con location 5 y así sucesivamente.

Y ahora mismo una parte interesante . También creamos solo un índice (aunque este es un índice compuesto, sigue siendo un índice) podemos usarlo para encontrar rápidamente el elemento

  • solo por el item . Realmente todo lo que tenemos que hacer es sólo el primer paso. Por lo tanto, no tiene sentido crear otro índice {ubicación:1} porque ya está cubierto por un índice compuesto.
  • también podemos encontrar rápidamente solo por item and by location (solo necesitamos 2 pasos).

Cool 1 índice pero nos ayuda de tres maneras diferentes. Pero espera un minuto:¿qué pasa si queremos buscar por item and stock? . Oh, parece que también podemos acelerar esta consulta. Podemos en log(n) encontrar todos los elementos con un ítem específico y... aquí tenemos que parar - la magia ha terminado. Necesitamos iterar a través de todos ellos. Pero sigue siendo bastante bueno.

Pero que nos pueda ayudar con otras consultas. Veamos una consulta por location que parece que ya fue ordenado. Pero si lo miras, verás que esto es un desastre. Uno al principio y luego otro al final. No puede ayudarte en absoluto.

Espero que esto aclare algunas cosas:

  • por qué los índices son buenos (reducen el tiempo de O(n) a potencialmente O(log(n))
  • por qué los índices compuestos pueden ayudar con algunas consultas; sin embargo, no hemos creado un índice en ese campo en particular y ayudamos con algunas otras consultas.
  • qué índices cubre el índice compuesto
  • por qué los índices pueden dañar (crean una estructura de datos adicional que debe mantenerse)

Y esto debería decir otra cosa válida:el índice no es una panacea. . No puede acelerar todas sus consultas, por lo que suena tonto pensar que creando índices en todos los campos TODO sería súper rápido.