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

Manejo de consultas lentas en MongoDB

Cuando está en producción, una aplicación debe brindar una respuesta oportuna al usuario con el fin de mejorar la interacción del usuario con su aplicación. A veces, sin embargo, las consultas de la base de datos pueden comenzar a retrasarse, por lo que la latencia de una respuesta llega al usuario o, más bien, la operación de rendimiento finaliza debido a que se superó el tiempo de espera promedio establecido.

En este blog vamos a aprender cómo puede identificar estos problemas en MongoDB, formas de solucionarlos cuando se presenten y cuáles son las posibles estrategias a emprender para que esto no vuelva a suceder.

Más a menudo, lo que conduce a respuestas de consulta lentas es una capacidad de CPU degradada que no puede soportar el conjunto de trabajo subyacente. El conjunto de trabajo en este caso es la cantidad de datos e índices que estarán sujetos a una instancia de rendimiento, por lo tanto, activa en ese momento. Esto se considera especialmente en la planificación de la capacidad cuando se espera que la cantidad de datos involucrados aumente con el tiempo y la cantidad de usuarios que interactúan con su plataforma.

Identificación de un problema de consulta lenta

Hay dos formas de identificar consultas lentas en MongoDB.

  1. Uso del generador de perfiles
  2. Uso del asistente db.currentOp()

Uso del generador de perfiles de MongoDB

El generador de perfiles de base de datos en MongoDB es un mecanismo para recopilar información detallada sobre los comandos de la base de datos ejecutados en una instancia de mongod en ejecución, es decir:operaciones de rendimiento (Crear, Leer, Actualizar y Eliminar) y los comandos de configuración y administración.

El generador de perfiles utiliza una colección limitada llamada system.profile donde escribe todos los datos. Esto significa que, cuando la colección está llena en términos de tamaño, los documentos más antiguos se eliminan para dar lugar a nuevos datos.

El generador de perfiles está desactivado de forma predeterminada, pero dependiendo del nivel de creación de perfiles, se puede habilitar por base de datos o por instancia. Los posibles niveles de perfilado son:

  • 0:el generador de perfiles está desactivado, por lo tanto, no recopila ningún dato.
  • 1:el generador de perfiles recopila datos para operaciones que tardan más que el valor de slowms
  • 2- el generador de perfiles recopila datos para todas las operaciones.

 Sin embargo, habilitar la generación de perfiles genera un impacto en el rendimiento de la base de datos y el uso del disco, especialmente cuando el nivel de generación de perfiles se establece en 2 . Se deben considerar las implicaciones de rendimiento antes de habilitar y configurar el generador de perfiles en una implementación de producción.

Para configurar la generación de perfiles, usamos el asistente db.setProfilingLevel() como:

db.setProfilingLevel(2)

Un documento de muestra que se almacenará en la colección system.profile será:

{ "was" : 0, "slowms" : 100, "sampleRate" : 1.0, "ok" : 1 }

El par clave-valor “ok”:1 indica que la operación tuvo éxito, mientras que slowms es el umbral de tiempo en milisegundos que debe tomar una operación y, de forma predeterminada, es 100 ms.

Para cambiar este valor

db.setProfilingLevel(1, { slowms: 50 })

Para consultar datos en la recopilación system.profile, ejecute:

db.system.profile.find().pretty()

Uso de db.currentOp()helper

Esta función enumera las consultas en ejecución actuales con información muy detallada, como cuánto tiempo han estado ejecutándose. En un shell mongo en ejecución, ejecuta el comentario, por ejemplo:

db.currentOp({“segs_running”:{$gte:5}}) 

Donde secs_running es la estrategia de filtrado para que solo se devuelvan las operaciones que hayan tardado más de 5 segundos en realizarse, lo que reduce el resultado. Esto se usa a menudo cuando la salud de la CPU se puede calificar al 100% debido al impacto adverso en el rendimiento que puede implicar en la base de datos. Entonces, al cambiar los valores, aprenderá qué consultas tardan más en ejecutarse.

Los documentos devueltos tienen como claves de interés las siguientes:

  • consulta :lo que implica la consulta
  • activo : si la consulta aún está en curso.
  • ns :nombre de la colección contra la que se ejecutará la consulta
  • segundos_corriendo :  duración de la consulta hasta ahora en segundos

Al resaltar qué consultas tardan más, ha identificado qué está sobrecargando la CPU.

Interpretación de resultados y solución de problemas

 Como hemos descrito anteriormente, la latencia de las consultas depende en gran medida de la cantidad de datos involucrados que, de lo contrario, conducirán a planes de ejecución ineficientes. Es decir, por ejemplo, si no usa índices en su colección y desea actualizar ciertos registros, la operación debe pasar por todos los documentos en lugar de filtrar solo aquellos que coinciden con la especificación de la consulta. Lógicamente, esto llevará más tiempo, lo que conducirá a una consulta lenta. Puede examinar un plan de ejecución ineficiente ejecutando: explique('executionStats') que proporciona estadísticas sobre el rendimiento de la consulta. Desde este punto, puede aprender cómo la consulta está utilizando el índice además de proporcionar una pista si el índice es óptimo.

Si regresa el ayudante de explicación

{

   "queryPlanner" : {

         "plannerVersion" : 1,

         ...

         "winningPlan" : {

            "stage" : "COLLSCAN",

            ...

         }

   },

   "executionStats" : {

      "executionSuccess" : true,

      "nReturned" : 3,

      "executionTimeMillis" : 0,

      "totalKeysExamined" : 0,

      "totalDocsExamined" : 10,

      "executionStages" : {

         "stage" : "COLLSCAN",

         ...

      },

      ...

   },

   ...

}

queryPlanner.winningPlan.stage:el valor de la clave COLLSCAN indica que mongod tuvo que escanear todo el documento de la colección para identificar los resultados, por lo que se convierte en una operación costosa y, por lo tanto, genera consultas lentas.

executionStats.totalKeysExamined:0 significa que la colección no utiliza la estrategia de indexación

Para una consulta dada, el número de documentos involucrados debe ser cercano a cero. Si el número de documentos es bastante grande, hay dos posibilidades:

  1. No usar la indexación con la colección
  2. Usando un índice que no es óptimo.

Para crear un índice para una colección, ejecute el comando: 

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

Donde cantidad es un campo de ejemplo que ha seleccionado como óptimo para la estrategia de indexación.

Si desea obtener más información sobre la indexación y qué estrategia de indexación usar, consulte este blog

Conclusión

La degradación del rendimiento de la base de datos se puede representar fácilmente al tener consultas lentas, que es la menor expectativa que nos gustaría que encontraran los usuarios de la plataforma. Uno puede identificar consultas lentas en MongoDB habilitando el generador de perfiles y configurándolo según algunas especificaciones o ejecutando db.currentOp() en una instancia de mongod en ejecución.

Al observar los parámetros de tiempo en el resultado devuelto, podemos identificar qué consultas están retrasadas. Después de identificar estas consultas, usamos el asistente de explicación en estas consultas para obtener más detalles, por ejemplo, si la consulta usa algún índice.

Sin la indexación, las operaciones se vuelven costosas ya que es necesario escanear muchos documentos antes de aplicar los cambios. Con este contratiempo, la CPU trabajará en exceso, lo que dará como resultado consultas lentas y picos de CPU crecientes.

El principal error que conduce a consultas lentas es una planificación de ejecución ineficiente que se puede resolver fácilmente mediante el uso de un índice con la colección involucrada.