Consulta SQL++ / N1QL

Pruebas de ANSI JOIN

Visión general

El objetivo principal de este artículo es mostrar cómo se prueban los ANSI JOINs de Couchbase. En Couchbase versión 5.5ahora puede ejecutar uniones utilizando la sintaxis estándar ANSI. Esta adición a las uniones las hace mucho más flexibles, pero también mucho más complejas. Esta complejidad hace que sea difícil para nosotros probar en nuestro marco normal, simplemente hay demasiadas posibilidades para escribir manualmente para la automatización. Por suerte, uno de nuestros marcos de pruebas nos permite establecer los parámetros de una consulta y, a continuación, genera conjuntos aleatorios de consultas basados en esos parámetros. Este marco se conoce como Generador de consultas aleatorias (RQG). En este artículo discutiremos como RQG es usado para probar la funcionalidad ANSI JOIN que fue implementada. En primer lugar, vamos a echar un breve vistazo a lo que es diferente con ANSI JOINs.

En este artículo repasaremos los siguientes temas:

1. Introducción a los JOIN ANSI

2. Visión general del generador de consultas aleatorias (RQG)

3. USO DE RQG para probar ANSI JOINs

4. Puntos clave

5. Lista de errores adicionales encontrados en ANSI JOIN

6. Anexo

Introducción a los JOIN ANSI

Anteriormente en Couchbase sólo se podían ejecutar lookup joins y uniones de índices. Esto era bueno para las consultas en las que un lado de la unión puede producir una clave de documento del otro lado de la unión. Sin embargo, el problema con esto es que las uniones no podían ejecutarse en otros campos de un espacio de claves. Las uniones ANSI solucionan este problema y lo llevan un paso más allá, ahora las uniones se pueden ejecutar en campos arbitrarios o expresiones que dan como resultado campos, o en múltiples condiciones de unión.

Sintaxis antigua de Join:

        Lhs-keyspace [join-type] JOIN rhs-keyspace

ON KEYS [expresión que da como resultado un meta().id de uno de los espacios de claves].

Sintaxis ANSI JOIN:

lhs-expresión [join-tipo] JOIN rhs-espacio-clave ON [join-condición].

Consulta de sintaxis de unión antigua:

Misma consulta con ANSI JOINs Sintaxis:

Los tipos de join soportados en N1QL son INNER JOIN o LEFT/RIGHT OUTER JOIN. Si simplemente pone JOIN se interpretará como INNER JOIN, y LEFT/RIGHT JOIN se interpretará como OUTER JOIN. En la nueva sintaxis de join, el lado izquierdo del join puede ser un espacio clave, una consulta n1ql anidada, una expresión n1ql o un join propiamente dicho. El lado derecho del join debe ser un keyspace en la implementación actual de ANSI JOINs dentro de Couchbase. La cláusula ON contiene las condiciones que la unión debe cumplir, estas condiciones pueden ser cualquier expresión predicada siempre y cuando haya un índice apropiado en el espacio clave del lado derecho. Así que puedes hacer comparaciones de igualdad y comparaciones de no igualdad (b1.field = b2.field o b1.field/=/!=/b2.field o b2.field is NOT NULL o expresión compleja = b2.field) Esto es un breve vistazo a la nueva característica, para una inmersión más profunda en la característica por favor revisa esta entrada de blog escrita por Bingjie Miao (el desarrollador que implementó la característica): https://www.couchbase.com/blog/ansi-join-support-n1ql/

Ahora empezamos a entender que los JOINs ANSI tienen muy pocas limitaciones en comparación con nuestros antiguos joins. El lado izquierdo de un ANSI join puede ser muy complejo, incluso puede ser varios joins en sí mismo, o una consulta anidada que resulta en algunos datos json, o varias consultas anidadas. Debido a este nivel de complejidad, es una mejor idea utilizar algo que llamamos RQG, en lugar de venir con consultas individuales para probar. He aquí un breve resumen de cómo funciona RQG.

Descripción general del generador de consultas aleatorias (RQG)

RQG es un framework escrito por Couchbase que aprovecha otro framework llamado Randgen. Básicamente especificamos un conjunto de parámetros en un archivo llamado gramática, y a partir de esos parámetros Randgen creará plantillas de consulta SQL (consultas con marcadores de posición para los nombres de campo y nombres de tabla), entonces nuestro marco procesa estas plantillas y las convierte en consultas con formato N1QL basadas en el conjunto de datos que se carga en couchbase.

Ejemplo de plantilla de consulta:

Esta plantilla se genera a partir del archivo de gramática que contiene los parámetros, básicamente el archivo de gramática le dice a randgen que genere una consulta que seleccione una lista de datos de tipo numérico de una unión de dos cubos arbitrarios en una comparación de igualdad. La gramática tendrá varios tipos de campos para seleccionar y varias condiciones de unión que se pueden introducir en los predicados ON/ WHERE. Una vez generada la plantilla como se muestra arriba, nuestro marco de trabajo reemplazará estos valores arbitrarios con valores basados en los datos cargados. Para NUMERIC_FIELD_LIST seleccionará un campo que es una lista de ints/bigints/floats/decimals/etc dependiendo de lo que esté disponible. El framework sustituirá BUCKET_NAME por el nombre específico de un bucket que exista en el servidor. PREVIOUS_TABLE.FIELD será un campo del primer bucket y CURRENT_TABLE.FIELD será el mismo campo del segundo bucket. Una vez hecho esto, se repasará la consulta y se creará una copia de la misma en la que se eliminarán las diferencias entre N1QL y SQL. Por ejemplo, en la antigua sintaxis join no podíamos usar la palabra clave ON, así que en su lugar RQG convertiría ON a ON KEYS para las consultas n1ql.

Ejemplo de consulta convertida:

A continuación, tanto las consultas n1ql como las consultas sql se ejecutan contra el servidor couchbase y un servidor MySQL equivalente. Los resultados de las consultas N1QL se comparan con los resultados de las consultas MySQL equivalentes. Nuestro objetivo es que nuestros resultados coincidan con los resultados de MySQL porque queremos que N1QL sea funcionalmente similar a SQL. Si quieres leer más acerca de cómo está diseñado RQG o cómo genera plantillas y las convierte a n1ql por favor revisa esta serie de 5 partes sobre RQG: https://dzone.com/articles/testing-n1ql-sql-for-json

USO DE RQG para comprobar los JOIN ANSI

La forma en que está configurado RQG nos permite generar una gran variedad de consultas que de otro modo no se nos habrían ocurrido a nosotros mismos. He aquí una plantilla extremadamente complicada generada por RQG:

Como puede ver por el tamaño de esta consulta, habría sido muy difícil crearla por nuestra cuenta, y muchas consultas de este tipo se generan y ejecutan a través de RQG. Esta capacidad de crear consultas muy complejas lo hace perfectamente adecuado para abordar la complejidad arbitraria de los JOINs ANSI. La gramática que hemos definido para probar las uniones ANSI intenta capturar la complejidad del lado izquierdo de una unión, así como la complejidad de la cláusula ON. Le decimos a RQG que genere el lado izquierdo de un join como una de estas tres cosas, un keyspace normal, una subconsulta n1ql o varios joins anidados. Le decimos a RQG que genere el lado derecho de una unión como espacio de claves. A continuación, le decimos a RQG que genere el Cláusula ON de un join como predicados mayoritariamente de igualdad entre dos campos uno del espacio clave izquierdo o alias izquierdoy una del espacio de llaves de la derecha. Las otras cosas que se pueden generar en la cláusula ON podrían ser comparaciones de no igualdad (/=/!=) o simplemente comprobar atributos del campo keyspace de la derecha (b2.campo no es nulo, b2.campo no falta, b2.campo está en una lista, etc). Para ANSI JOINs, hay una pequeña diferencia entre n1ql y sql. Esa diferencia es que N1QL soporta la comparación IS (NOT) MISSING, esto es debido al modelo de datos no relacional. Algunos buckets pueden tener documentos que tienen un campo que otros documentos en ese bucket no tienen. Entonces IS (NOT) MISSING significa que el campo no aparece en el documento(o en el caso de IS NOT MISSING significa que el campo aparece en el documento). Técnicamente, si quisiéramos también podríamos decirle a RQG que genere subconsultas n1ql dentro de la cláusula ON y las compare con los valores del espacio clave de la derecha, sin embargo esto incrementaría exponencialmente el tiempo de ejecución de nuestras consultas y no es un caso de uso común. A continuación se muestran algunos ejemplos de consultas ANSI JOIN generadas a partir de los parámetros anteriores:

Como se puede ver en estos ejemplos, la cláusula ON puede ser varios predicados encadenados, encadenados por AND/OR. También podemos observar que se pueden ejecutar varias uniones en una consulta, y que cada unión puede tener su propia cláusula ON.

Ahora que se entiende cómo RQG genera las plantillas y qué aspecto tienen esas plantillas, veamos un ejemplo de un error que encontramos en la funcionalidad ANSI JOIN que probablemente no habríamos encontrado de otra forma. MB-27483, en este fallo teníamos la siguiente consulta:

Esta consulta debería haberse ejecutado con éxito dada la forma en que nuestro servidor estaba configurado, sin embargo, en lugar de ejecutarse estaba lanzando un error que el índice adecuado no existía en el espacio clave de la derecha. El problema aquí era que la cláusula WHERE estaba interfiriendo con la selección del índice de la cláusula ON, causando que la consulta pensara que no tenía el índice que necesitaba cuando de hecho ese índice existía. Si examinamos la cláusula WHERE vemos que es muy compleja, no es el nivel de complejidad que normalmente tendríamos en la parte funcional de las pruebas. Por lo tanto, no habríamos detectado este error sin utilizar RQG.

Puntos clave

Los JOIN ANSI son bastante flexibles en cuanto a lo que es posible unir, se pueden unir expresiones arbitrarias con espacios clave y la cláusula ON puede contener predicados que comparen expresiones arbitrarias con campos. Este nivel de complejidad hace que sea poco práctico intentar crear consultas específicas para probar cada escenario por nuestra cuenta mediante pruebas funcionales. Por suerte, disponemos de un marco de trabajo llamado RQG que es capaz de generar consultas basadas en un conjunto de reglas que podemos definir. Esta funcionalidad es muy potente y nos ha permitido probar ANSI JOINs a nuestra satisfacción. Por ejemplo, si se ejecuta un gran número de consultas complejas, los resultados de ANSI JOIN se desviarán en 1. Sin embargo, si se ejecuta una de esas consultas de forma aislada, los resultados serán correctos. Por eso confiamos en que los ANSI JOIN estén en buena forma y listos para el uso de los clientes.

Lista de errores adicionales de ANSI JOIN encontrados con RQG:

Número de error Descripción del fallo
MB-27834 Esta consulta no utilizaba correctamente la sugerencia de consulta LIMIT, ejecutaba toda la consulta antes de aplicar el LIMIT
MB-27763 Esta consulta no utilizaba correctamente la sugerencia de consulta LIMIT, similar al error anterior
MB-27483 La consulta pensaba que el índice apropiado no existía, lo que provocaba un error. Sin embargo, el índice estaba realmente presente en el sistema
MB-27230 La consulta devolvía un error incorrecto
MB-27201 Esta consulta se estaba ejecutando en un error con relleno no funciona correctamente
MB-27109 Otra consulta que pensaba que el índice que necesitaba no estaba disponible, aunque el índice estaba presente en el sistema
MB-27028 Cuando se ejecutaban varias consultas seguidas, algunos de los resultados se desviaban en 1. Cuando las consultas se ejecutaban solas, todos los resultados eran correctos.
MB-26649 La consulta se colgaba intermitentemente

Anexo

  1. Blog de Couchbase Server 5.5 GA https://www.couchbase.com/blog/announcing-couchbase-server-5-5/
  2. Uniones por índices https://dzone.com/articles/join-faster-with-couchbase-index-joins
  3. ANSI JOINs Blog de Couchbase https://www.couchbase.com/blog/ansi-join-support-n1ql/
  4. Randgen https://launchpad.net/randgen
  5. Serie de artículos RQG Dzone https://dzone.com/articles/testing-n1ql-sql-for-json
Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Ajay Bhullar

Ajay Bhullar es un Software Engineer Tester en Couchbase desde hace 2 años. Ajay está trabajando en cómo se prueban los JOINs ANSI de Couchbase y en la versión 5.5 de Couchbase, cómo se pueden ejecutar joins usando la sintaxis estándar ANSI.

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.