SQL ha sido el idioma común para el análisis de datos estructurados durante varias décadas, y hemos trabajado mucho en los últimos años para admitir ANSI SQL y las diversas extensiones para hacer que SQL sea más agradable de usar en Databricks. Hoy, nos complace anunciar la sintaxis de tubería SQL, la extensión más grande que hemos implementado en los últimos años para hacer que SQL sea drásticamente más fácil de escribir y entender, de manera totalmente compatible con versiones anteriores.
Uno de los desafíos clave en SQL hasta ahora radica en el orden de la “lógica”. Al escribir una consulta, muchos autores piensan en términos de los siguientes pasos lógicos: identificar la lista de tablas a consultar, unirlas, filtrar filas no deseadas y, finalmente, agregar. Este orden lógico se puede expresar de la siguiente manera:
La consulta SQL para estos pasos se vería así:
En lugar de escribir los pasos en orden (1, 2, 3), debemos escribirlos en el orden (3, 2, 1). Esto es confuso y el problema solo se agrava a medida que agregamos más lógica y pasos a cada consulta.
En contraste, pensemos en los DataFrames. Una gran fuente de la popularidad original de Apache Spark entre los científicos de datos es la potente capacidad de sus API de DataFrame de Scala y Python. Los programas pueden aplicarlas para expresar su lógica en un orden natural de pasos. Comenzando desde la tabla de origen, los usuarios pueden encadenar operaciones independientes y componibles una tras otra, lo que facilita la construcción de transformaciones de datos complejas en una secuencia clara e intuitiva.
Este diseño promueve la legibilidad y simplifica la depuración manteniendo la flexibilidad. Es una razón importante por la que Databricks ha logrado su enorme crecimiento en la industria hasta ahora en el espacio de la gestión de datos, y este impulso solo continúa aumentando hoy.
Así es como se ve la misma lógica en PySpark DataFrames:
Este enfoque admite la iteración flexible sobre ideas. Sabemos que los datos de origen existen en algún archivo, por lo que podemos comenzar de inmediato creando un DataFrame que represente esos datos como una relación. Después de pensar un poco, nos damos cuenta de que queremos filtrar las filas por la columna de cadena. Bien, entonces podemos agregar un paso .filter al final del DataFrame anterior. Oh, y queremos calcular una proyección al final, así que lo agregamos al final de la secuencia.
Muchos de estos usuarios desean que SQL se comporte de manera más similar a los lenguajes de datos modernos como este. Históricamente, esto no era posible, y los usuarios tenían que elegir una forma de pensar o la otra.
Avancemos rápido hasta hoy: ¡ahora es posible tener lo mejor de ambos mundos! La sintaxis de tubería hace que SQL sea más fácil de escribir, leer y extender más tarde, y nos libera de esta confusión al permitirnos usar los mismos pasos en el orden en que los pensamos.
En la conferencia VLDB 2024, Google publicó un artículo industrial que propone esto como un nuevo estándar. Los ingenieros de procesamiento de consultas han implementado esta funcionalidad y la han habilitado por defecto en Apache Spark 4.0 (documentación) y Databricks Runtime 16.2 (documentación) en adelante. Es compatible con versiones anteriores con la sintaxis SQL normal: los usuarios pueden escribir consultas completas usando esta sintaxis, solo ciertas subconsultas o cualquier combinación útil.
El artículo industrial proporciona la consulta 13 del benchmark TPC-H como primer ejemplo:
Usando la sintaxis de tubería para expresar la misma lógica, aplicamos operadores en una secuencia de principio a fin con cualquier orden arbitrario:
Con SQL normal, cuando queremos recopilar filas en grupos basándonos en valores de columnas o expresiones, agregamos una cláusula GROUP BY al final de la consulta SQL en construcción. Las agregaciones a realizar permanecen atrapadas hasta el final de la lista SELECT al principio de la consulta y cada expresión debe ser ahora:
Cualquier elemento de SELECT que no cumpla una de estas categorías generará un error como “la expresión X apareció en la lista SELECT pero no fue agrupada ni agregada”.
Las reglas de la cláusula WHERE también cambian:
La sintaxis de tubería resuelve esto separando cada operación de agregación (con posible agrupación) en un paso dedicado que puede aplicarse en cualquier momento. Solo las expresiones con funciones de agregación dentro pueden aparecer en este paso, y las funciones de agregación no pueden aparecer dentro de los pasos |> SELECT. Si el autor de SQL olvida alguno de estos invariantes, los mensajes de error resultantes son muy claros y fáciles de entender.
Tampoco es necesario repetir las expresiones de agrupación, ya que podemos escribirlas en una sola cláusula GROUP BY.
Veamos el ejemplo anterior con una agregación añadida al final, que devuelve una tabla de resultados con dos columnas L, M:
SQL normal generalmente requiere que las cláusulas aparezcan en un orden específico, sin repetición. Si queremos aplicar operaciones adicionales al resultado de una consulta SQL, la forma de hacerlo es usar una subconsulta de tabla en la que envolvemos la consulta original entre paréntesis y la usamos en la cláusula FROM de una consulta envolvente. La consulta al principio de esta publicación muestra un ejemplo simple de esto.
Tenga en cuenta que este anidamiento puede ocurrir un número arbitrario de veces. Por ejemplo, aquí está la consulta 23 de TPC-DS:
¡Se está volviendo confuso y más difícil de leer con todos los niveles de paréntesis y sangría!
Por otro lado, con la sintaxis de tubería de SQL no hay necesidad de subconsultas de tablas en absoluto. Dado que los operadores de tubería pueden aparecer en cualquier orden, podemos simplemente agregar nuevos al final en cualquier momento, y todos los pasos siguen funcionando de la misma manera.
La sintaxis de tubería rehace cómo los autores escriben, leen y extienden SQL. Podría parecer un desafío cambiar la forma de pensar de cómo funciona el SQL normal a este nuevo paradigma. Es posible que incluso tengas un gran volumen de consultas SQL existentes escritas previamente que eres responsable de mantener y posiblemente extender más adelante. ¿Cómo podemos hacer que esto funcione con dos sintaxis SQL?
Afortunadamente, esto no es un problema con nuestra nueva sintaxis SQL. Es totalmente interoperable con SQL normal, donde cualquier consulta (o subconsulta de tabla) puede aparecer usando cualquiera de las dos sintaxis. Podemos empezar a escribir nuevas consultas usando la sintaxis de tubería de SQL y mantener las anteriores si es necesario. Incluso podemos empezar a reemplazar las subconsultas de tablas de nuestras consultas anteriores con la nueva sintaxis y mantener todo lo demás igual, como actualizar solo una parte de TPC-H Q13 desde el principio de esta publicación:
Dado que los operadores de tubería de SQL pueden seguir cualquier consulta válida, también es posible empezar a agregarlos a consultas SQL normales existentes. Por ejemplo:
La sintaxis de tubería de SQL está lista para que la pruebes en Databricks Runtime versión 16.2 y posteriores. O descarga Apache Spark 4.0 y pruébala en el mundo de código abierto. La sintaxis se ajusta al documento industrial Pipe Syntax in SQL, por lo que la nueva sintaxis será portable con Google BigQuery, así como con el proyecto de código abierto ZetaSQL.
Esta sintaxis también está empezando a generar interés en la comunidad y a aparecer en otros lugares, aumentando la portabilidad ahora y con el tiempo.
Pruébala y experimenta los beneficios de hacer que las consultas SQL sean más fáciles de escribir para usuarios nuevos y experimentados, y haz que la legibilidad y extensibilidad futuras sean más sencillas al reducir la incidencia de subconsultas complejas en favor de operadores claros y componibles en su lugar.
(Esta entrada del blog ha sido traducida utilizando herramientas basadas en inteligencia artificial) Publicación original
