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

MongoDB Regex, índice y rendimiento

MongoDB admite expresiones regulares mediante el operador $regex. Sin embargo, estas consultas de expresión regular de MongoDB tienen un inconveniente, todos menos un tipo de expresión regular hacen un uso deficiente de los índices y provocan problemas de rendimiento. Para un servidor de producción con grandes cantidades de datos, una consulta de expresión regular incorrecta puede poner de rodillas a su servidor.

Las consultas basadas en expresiones regulares de MongoDB son una consulta bastante común en la mayoría de las aplicaciones que utilizan MongoDB. Esto es similar a la operación 'LIKE' admitida en la mayoría de las bases de datos relacionales. La sintaxis del comando es la siguiente

{ $regex: /pattern/, $options: '<options>' }
E.g. { name: { $regex: /^acme.*test/}}

Para obtener información más detallada sobre la operación de expresiones regulares y opciones adicionales, consulte la documentación de MongoDB

Para el resto de esta discusión, supondremos que el campo con el que está comparando tiene un índice. Si no indexa, se realizará un análisis de la colección y un rendimiento muy bajo. Sin embargo, incluso si el campo está indexado, puede tener un rendimiento deficiente. La razón es que MongoDB puede hacer un buen uso de los índices solo si su expresión regular es una "expresión de prefijo":estas son expresiones que comienzan con el carácter "^".

P.ej. { nombre: { $regex: /^acme/}}

Esto permite que MongoDB identifique un rango de entradas de índice que son relevantes para esta consulta y da como resultado consultas eficientes. Cualquier otra consulta da como resultado un escaneo de índice ya que MongoDB no puede limitar el escaneo a un rango de entradas de índice. Un escaneo de índice es particularmente malo ya que todos los índices deben paginarse en la memoria y esto afecta el conjunto de trabajo de su servidor (de hecho, el escaneo de índice podría conducir a un peor rendimiento que un escaneo de colección:resulta en el doble de errores de página). ).

Veamos algunos ejemplos y los planes de consulta resultantes. Para nuestros propósitos de prueba, he configurado una colección con 100k documentos. Cada documento tiene un campo firstName que es una cadena de 16 caracteres.

Ejemplo 1: { nombre:{ $regex:/^acme/}}
Resultado:uso eficiente del índice
Plan de consulta:

executionStats" : {
       "executionSuccess" : true,
       "nReturned" : 0,
       "executionTimeMillis" : 0,
       "totalKeysExamined" : 1,
       "totalDocsExamined" : 0,

Ejemplo 2: { nombre:{ $regex:/^acme/i}}
Resultado:análisis de índice ineficaz debido a un requisito que no distingue entre mayúsculas y minúsculas. Entonces, básicamente, la opción /i niega la "expresión de prefijo"
Plan de consulta:

        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 137,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,

Ejemplo 3: { nombre:{ $regex:/acme.*corp/}}
Resultado:análisis de índice ineficiente
Plan de consulta:

                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 167,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,

Ejemplo 4: { nombre:{ $regex:/acme/}}
Resultado:escaneo de índice ineficiente

        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 130,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,