Analizando el performance en mongo db
Cuando nuestros aplicativos empiezan a crecer y con ello nuestros datos uno de los puntos mas caoticos es mantener un buen perforance de base de datos, es decir queremos que nuestras consultas sean igual de rapidas que antes.
Para esto vamos a apoyarnos de una herramienta nativa en mongodb y es el commando explain. Para este ejemplo trabajare con una base de datos llamada MyDb y una colección de nombre Cum, mi versión de mongo es 4.2.10, los queries los genero desde robo 3T (no es necesario usarlo) y la estructura de los documentos es la siguiente:
{
"_id" : ObjectId("5f95be691f95db34ebc68eb8"),
"key" : "19937041-02 - DEXAMETASONA - 1.0 - mg",
"id" : "19937041-02",
"cum" : "19937041-02",
"expediente" : 19937041,
"consecutivo" : 2,
"descripcion" : "ANTIBIOTICOS EN COMBINACION CON OTROS F RMACOS 1.0 mg DEXAMETASONA",
"registrosanitario" : "INVIMA 2019M-0002783-R2",
"estadoregistro" : "Vigente",
"fechavencimiento" : "11/01/2024",
"atc" : "S01AA20"
}
La collección no tiene indices creados excepto uno que esta por defecto y es el _id.
Realizando queries
Bueno ahora vamos a hacer dos consultas sencillas:
1- Traer los registros con cum = 9813–10
2- Traer los registros estadoregistro = Vigente
En ambos casos nos devuelve 1 y 41.239 registros respectivamente. Pero aqui empiezan las preguntas
¿Que tiempo le tomó hacer esta consulta?
¿Existe una mejor manera?
Es hora de usar nuestro comando explain() agregando un parametro.
Nos devolvera un objeto muy grande pero vamos a centrarnos en las propiedades: winningPlan y executionStats.
WinningPlan
Esta dentro de queryPlanner y nos dira que metodo usó el motor de mongo db para hacer la consulta es decir, si uso indices y cuales fueron, si recorrio toda la colección, si aplico algun sort para ordenar los datos y mas...
De la anterior imagen tenemos:
Stage: hace referencia al plan usado para realizar la consulta, puede constituir de una o varias etapas. Algunos de sus posibles valores son:
COLLSCAN
recorre toda la colecciónIXSCAN
usa indicesFETCH
cuando hubo una etapa anterior y examina los documentos devueltos por esa etapa.
Filter: el query ejecutado en esa etapa para este caso { cum: “9813–10” } de ahi el $eq (equal).
Direction: hacia donde se hizo la consulta de nuestro dato de forma hacia delante (forward) desde el ultimo registro hasta el primero (backward).
Para nuestro caso particular podremos decir que recorrio toda la colección hacia delante encontrando todas con cohincidencias de cum = 9813–10
ExecutionStats
Retornara estadisticas de nuestra consulta como: en cuantos documentos busco, cuantos retorno, tiempo que le tomo devolver los documentos y mas…
De la anterior imagen tenemos:
ExecutionSuccess: si la consulta se ejecutó de forma correcta.
nReturned: número de elementos retornados.
ExecutionTimeMillis: tiempo en milisegundos que tomo hacer la busqueda.
TotalKeysExamined: Indices examinados.
TotalDocsExamined: total de documentos examinados.
Poniendo en contexto nuestro ejemplo podremos decir que tenemos 56.879 registros, que nuestra consulta recorrio toda esta colección para retornanos 1 dato y además que le tomo 54 milisegundos.
Vamos que 56k registros son pocos que pasaria si tenemos 1.000.000 o 10M … Pues que tendremos un gran problema si aplicamos esta consulta en nuestros aplicativos.
Mejorar las estadisticas
Existen varias formas de mejorar la velocidad de las consulas, para este caso usaremos un indice simple en Cum de forma ascendente (en otra historia trataremos mejor el tema de indices en mongodb).
Ahora vuelvo a correr la consulta:
Nos aparecen nuevas propiedades y entre ellas 2 stage, el padre que uso el plan FETCH para buscar lo que el stage hijo le devolvio, este stage hijo uso un plan IXSCAN, es decir, tuvo en cuenta el indice.
Que nos dicen las estadisticas ¿ mejoro el proceso de busqueda ?
Wow nos dicen que buscó usando una llave (indice), que examino un solo documento y fue el que nos retorno, sin dejar a un lado que le tomo 0 milisegundos (en realidad si le toma un tiempo, vamos no significa que este mas alla del tiempo. Le tomo muy poco tiempo en realizar la consulta menos de 1 ms)
Espero que sea de ayuda.
Nos leemos en otras historias.