Consulta SQL++ / N1QL

Mejoras en el manejo de listas IN en Couchbase Server 6.5

Introducción

La lista IN es comúnmente usada en consultas N1QL. Couchbase Server 6.5 introduce un par de mejoras en el manejo de la lista IN en las consultas N1QL.

Manipulación de listas IN de gran tamaño

Antes de Couchbase Server 6.5 N1QL manejaba la evaluación de la lista IN en tiempo de ejecución de una manera simple, comparando con cada elemento de la lista IN sucesivamente hasta encontrar una coincidencia. Esto puede ser ineficiente si la lista IN es grande, es decir, si hay muchos elementos en la lista IN. Couchbase Server 6.5 introduce una mejora para el manejo de listas IN grandes en tiempo de ejecución. Cuando el número de elementos en la lista IN excede un umbral (actualmente 16), construye una tabla hash con todos los elementos de la lista IN. De esta forma, cada evaluación del predicado de la lista IN se convierte en un sondeo de la tabla hash en lugar de realizar muchas comparaciones con cada elemento de la lista IN.

Lista "estática" IN

Para que esta optimización funcione, la lista IN debe ser "estática", es decir, los valores de cada elemento de la lista IN no pueden cambiar durante una ejecución de la consulta. Puede tener una lista IN en la que todos los elementos sean constantes o parámetros de consulta, por ejemplo:

...... es sólo una abreviatura, tendrá que rellenar todos los valores si desea ejecutar la consulta.

Puede mezclar constantes y parámetros de consulta en la misma lista IN:

También puede utilizar un único parámetro de consulta para toda la lista IN:

y pasar la lista IN real como parámetro de consulta.

Esta optimización de la evaluación de la lista IN no funcionará si la lista IN no es "estática", por ejemplo, si algún elemento de la lista IN hace referencia a cualquier campo del documento:

En este caso, el valor del primer elemento de la lista IN cambia durante la ejecución, por lo que no podemos utilizar la optimización de la tabla hash para la evaluación de esta lista IN.

Cláusula IN con subconsulta

Como caso especial de la lista IN, puede tener una cláusula IN con una subconsulta:

Cuando se utiliza la palabra clave RAW y hay una única expresión en la lista de proyección, el resultado de la subconsulta es un array de valores. Cuando la subconsulta no está correlacionada, es decir, no hace referencia a ningún campo de la consulta principal, también se puede aplicar aquí la nueva optimización de utilizar una tabla hash para la evaluación del predicado de la lista IN. En tiempo de ejecución, después de que se ejecute la subconsulta y se conozca el resultado de la ejecución de la subconsulta, si el conjunto de resultados contiene más valores que el umbral, se construirá una tabla hash con todos los valores del conjunto de resultados, y la evaluación posterior del predicado de la subconsulta se convierte en una sonda a la tabla hash. Esta optimización de la lista IN puede aplicarse potencialmente varias veces en caso de subconsultas anidadas:

siempre que ambas subconsultas no estén correlacionadas y el tamaño del resultado de cada subconsulta supere el umbral.

NO EN MANEJO

La optimización del uso de una tabla hash para la evaluación de la lista IN también es aplicable al predicado NOT IN. El predicado NOT IN se evalúa del mismo modo que el predicado IN y el valor booleano resultante simplemente se invierte.

Visibilidad de la optimización de la tabla hash para la evaluación de la lista IN

La optimización para utilizar una tabla hash para evaluar una lista IN grande es puramente una optimización interna. Hay poco efecto visible externamente, excepto que la consulta se ejecuta más rápido. Debido al uso de una tabla hash, el consumo de memoria también aumenta ligeramente durante la ejecución de la consulta. El consumo adicional de memoria depende obviamente del tamaño de la tabla hash, que a su vez depende del número de elementos de la lista IN.

Generación dinámica de índices para parámetros de consulta como lista IN

Para un predicado de lista IN, si existe un índice apropiado, el planificador puede generar un escaneo de índice con múltiples spans, uno para cada elemento de la lista IN. Por ejemplo:

El escaneo del índice tendrá 3 spans generados:

Lo mismo ocurre si los parámetros de consulta se utilizan como elementos individuales en la lista IN:

Se generan los siguientes intervalos de índice:

Sin embargo, si se utiliza un parámetro de consulta como toda la lista IN:

A continuación, se genera un único vano de índice:

Observa que los límites inferior y superior del índice son array_min($inlist) y array_max($inlist) respectivamente. Cuando se utiliza un parámetro de consulta para toda la lista IN, en tiempo de compilación se desconoce el tamaño de la lista IN, por lo que es imposible pregenerar intervalos de índice para cada elemento de la lista IN. Utilizando el intervalo de índices generado actualmente, el escaneo de índices debe escanear entre los valores mínimo y máximo de los elementos del array. Por ejemplo, si el parámetro de consulta proporcionado para la ejecución de la consulta es [1, 1000, 1000000], entonces todo lo que está entre 1 y 1000000 es escaneado por el índice. Esto es muy ineficiente e implica mucho trabajo innecesario.

En Couchbase Server 6.5, el manejo de tales casos se ha mejorado generando dinámicamente índices en tiempo de ejecución. Cuando la consulta está siendo ejecutada, el valor del parámetro de consulta es ahora conocido, y por tanto el número de elementos de la lista IN también es conocido. El motor de ejecución intentará imitar los intervalos de índice generados cuando se conoce la lista IN en tiempo de compilación, generando dinámicamente un intervalo de índice distinto para cada elemento de la lista IN. Por ejemplo, si [1, 1000, 1000000] se especifica como $inlist para la ejecución de la consulta, el motor de ejecución en tiempo de ejecución generará 3 tramos de índice, de forma similar a cuando [1, 1000, 1000000] se especifica como una constante en la consulta. Esto permite que la exploración del índice sea mucho más precisa y evita explorar regiones innecesarias del índice.

El plan de explicación de la consulta sigue siendo el mismo, y sigue mostrando array_min($inlist) y array_max($inlist) como límites inferior y superior del intervalo del índice. Se añade un nuevo indicador "dynamic_in" al intervalo del índice:

La generación dinámica de índices se produce en tiempo de ejecución. Para evitar posibles problemas de rendimiento, existe un límite de 8192 espacios cuando los espacios de índice se generan dinámicamente. Si la lista IN introducida (como parámetro de consulta) tiene más de 8192 elementos, esta optimización no se aplicará.

Tratamiento de subconsultas y posible reescritura de consultas

El ejemplo anterior muestra la optimización de la generación dinámica de intervalos de índice cuando la lista IN es un parámetro de consulta. Esta optimización también es aplicable cuando la lista IN es una variable WITH o un parámetro de función. La variable WITH viene de otra nueva característica en Couchbase Server 6.5 - Common Table Expression (ver https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/with.html); el parámetro de función proviene de otra nueva característica de Couchbase Server 6.5 - Funciones Definidas por el Usuario (ver https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/userfun.html).

Sin embargo, cuando la cláusula IN utiliza una subconsulta, esta optimización no es aplicable. Por ejemplo: 

En este ejemplo, la cláusula IN tiene una subconsulta a la derecha. Si tiene definidos los siguientes índices

A continuación, la explicación de la consulta anterior muestra una exploración de índice en ix_route_1 con los siguientes intervalos:

Esto significa que el índice escanea todos los valores no NULL.

Es posible reescribir manualmente la consulta anterior para utilizar una cláusula WITH:

Si se observa la explicación de esta consulta reescrita, ahora la exploración del índice en ix_route_1 tiene los siguientes intervalos:

Para la consulta reescrita ahora puede tomar ventaja de la optimización para generar dinámicamente índice abarca en tiempo de ejecución.

Esta reescritura manual de la consulta para intentar aprovechar la nueva optimización de la generación dinámica de intervalos de índices sólo es posible cuando la subconsulta no está correlacionada. La reescritura manual de la consulta no se limita a una única subconsulta. También se puede realizar una reescritura manual similar para subconsultas anidadas, siempre que las subconsultas implicadas no estén correlacionadas. Por ejemplo, dada la siguiente consulta

Se puede reescribir a la siguiente consulta de tal manera que pueda aprovechar la optimización para generar dinámicamente los tramos del índice:

Si tiene definido el siguiente índice:

La explicación de la consulta reescrita muestra intervalos de índice similares en el índice ix_airline_1:

lo que indica que está en juego la optimización de la generación dinámica de intervalos de índices.

Resumen

Couchbase Server 6.5 introduce un par de mejoras en el manejo de listas IN. Cuando la lista IN es grande, se utiliza una tabla hash en tiempo de ejecución para la evaluación de la lista IN. Cuando un parámetro de consulta se especifica como la lista IN completa, la generación dinámica de índices en tiempo de ejecución permite realizar un escaneo de índices más eficiente. Ambas optimizaciones hacen que el manejo de la lista IN sea mucho más eficiente. En los casos en que la cláusula IN tiene una subconsulta no correlacionada, es posible reescribir manualmente la consulta utilizando expresiones de tabla comunes, para aprovechar la optimización de la generación dinámica de ámbitos de índice en tiempo de ejecución.

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Bingjie Miao, Ingeniero Principal de Software de Couchbase

Bingjie Miao es ingeniero de software principal en Couchbase. Bingjie tiene 20 años de experiencia en bases de datos relacionales y NoSQL. Su principal área de especialización es la optimización y ejecución de consultas.

4 Comentarios

  1. Perdón por utilizar el blog como medio de comunicación.. pero.. el formulario de contacto de vuestra web no funciona, y el email de contacto rebota diciendo que sólo los "miembros" pueden enviar emails.
    ¿Sigue Couchbase vivito y coleando? :/

    1. Denis Rosa, Defensor del Desarrollador, Couchbase febrero 21, 2020 a 12:42 pm

      ¿Has podido hablar con alguien?

  2. Hola Denis.

    Bingjie se puso en contacto conmigo.

    Gracias por responder :)

  3. Información muy útil, especialmente la tabla hash y CTE para la optimización de consultas.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.