¡Muy buenas a todos! Hoy quiero hablarles sobre uno de los proyectos a los que más atención le estoy prestando últimamente. Es una iniciativa que, sinceramente, creo que tiene muchísimo futuro, y a la cual quiero aportar en todo lo que pueda. No solo dándole visibilidad, sino también colaborando directamente en el código para ayudar a que alcance todo su potencial.
Estoy hablando de Sail, del equipo de LakeSail.
En aguas dominadas por gigantes marinos y tormentas de rayos, donde aún resuenan los golpes del martillo de Thor, Sail avanza como un drakkar ágil y preciso.
Mientras otros invocan chispas con estruendo, Sail navega ligero, sin peso innecesario, impulsado por la fuerza bruta de la eficiencia, abriendo el mar con determinación y control.
¿Qué es Sail? #
Como bien explican en su documentación:
Sail ⛵ es un motor de cómputo open-source, diseñado tanto para entornos de un solo nodo como para entornos distribuidos. Su misión es unificar el procesamiento por lotes, el procesamiento en tiempo real y las cargas de trabajo intensivas en cómputo (como las de IA).
Si ya estás usando Apache Spark, puedes cambiar a Sail sin necesidad de modificar tu código Spark, y beneficiarte de las ventajas que ofrece un lenguaje de programación moderno como Rust, además de principios de diseño pensados para el mundo del cómputo actual.
Sail está muy bien posicionado dentro del composable data stack. Está construido sobre bases sólidas como el formato en memoria Apache Arrow y el motor de consultas Apache DataFusion. Además, se está trabajando en integraciones con la librería de DataFrames Ibis, formatos lakehouse y distintos motores de almacenamiento en la nube.
La visión es que Sail te ayude a generar valor a gran escala a partir de tus datos, sin importar cómo ni dónde estén almacenados.
¿Por qué Sail? #
La clave de Sail radica en las tecnologías sobre las que está construido: Apache DataFusion y, en un nivel más fundamental, Apache Arrow. Para entender por qué elegimos estas herramientas, primero veamos qué aportan Apache Arrow y DataFusion.
Apache Arrow es una especificación abierta (agnóstica del lenguaje) que define un formato de datos columnar en memoria. En términos sencillos, Arrow organiza los datos por columnas en lugar de por filas, lo que permite aprovechar al máximo las capacidades de las CPU y GPU modernas. Este diseño logra un acceso a memoria secuencial de alto ancho de banda, mejor afinidad con la caché del procesador y la posibilidad de aplicar vectorización mediante instrucciones SIMD. El resultado práctico es que los algoritmos analíticos pueden ejecutarse de forma muchísimo más eficiente sobre datos en formato Arrow.
Apache Arrow y el modelo columnar #
En un formato columnar, los datos se almacenan agrupados por columnas en vez de mezclarse por filas. Es decir, todos los valores de una misma columna se ubican contiguamente en memoria, uno tras otro, en un búfer homogéneo. Esto contrasta con los layouts tradicionales row-based, donde cada fila almacena diversos campos de distintos tipos uno al lado del otro. Por ejemplo, en Apache Spark cada tarea suele procesar una partición compuesta por múltiples filas completas (cada una con todos sus campos mezclados). En cambio, con Arrow cada unidad de cómputo puede procesar una columna a la vez, operando sobre un solo tipo de dato a la vez para todos esos valores.
En resumen, la organización columnar de Arrow aporta varias ventajas clave:
-
Acceso secuencial y caché-amigable: Los operadores recorren la memoria de forma lineal, minimizando cache misses y lecturas aleatorias innecesarias.
-
Vectorización automática: Como todos los valores de un búfer son del mismo tipo, se pueden aprovechar instrucciones SIMD (por sus siglas en inglés, Single Instruction Multiple Data) para procesar centenares de valores en cada ciclo de reloj.
-
Interoperabilidad sin copias: Una columna creada en C++ se puede consumir directamente desde Python, Rust o Java sin necesidad de serializar ni duplicar los datos en memoria.
De esta manera, debido a que Arrow simplifica el acceso a los datos haciéndolos homogéneos y contiguos en memoria, esto habilita motores de ejecución muchísimo más ligeros y rápidos que los basados en filas, ya que eliminamos sobrecargas y aprovechamos al máximo la arquitectura del hardware.
Apache DataFusion #
Apache DataFusion es un motor de consultas analíticas escrito en Rust que se apoya completamente en el formato en memoria de Apache Arrow.
Gracias a este modelo columnar, DataFusion ejecuta consultas SQL de forma altamente eficiente, evitando conversiones innecesarias y aprovechando la vectorización (SIMD). Puede ejecutarse tanto en un único proceso como en entornos distribuidos, manteniendo siempre la misma representación de datos.
Incluye de forma nativa APIs en SQL y DataFrame, soporte para formatos como CSV, Parquet, JSON y Avro, bindings para Python, y una arquitectura flexible y extensible respaldada por una comunidad activa.
use datafusion::prelude::*;
use datafusion::error::Result;
#[tokio::main]
async fn main() -> Result<()> {
// Create a new dataframe with in-memory data using macro
let df = dataframe!(
"a" => [1, 2, 3],
"b" => [true, true, false],
"c" => [Some("foo"), Some("bar"), None]
)?;
df.show().await?;
Ok(())
}
Apache DataFusion forma parte de varios subproyectos destacables, entre los que se encuentran:
-
DataFusion Python, una interfaz en Python para ejecutar consultas SQL y DataFrame, con una experiencia muy similar a la de Pandas.
-
DataFusion Comet, un acelerador para Apache Spark construido sobre DataFusion. Hablaremos más en detalle sobre este proyecto en una próxima entrada del blog.
Vale, pero… ¿y Sail? #
Con todo este contexto, ¿dónde encaja Sail?
Sail actúa como un puente entre los data scientists acostumbrados a trabajar con PySpark y aquellas empresas cuya infraestructura analítica y procesos de ingenieria en producción se basan en aplicaciones desarrolladas con PySpark.
Lo que propone Sail es ofrecer una experiencia similar a PySpark, reutilizando la misma sintaxis, pero reemplazando el motor de ejecución de Spark por Apache DataFusion, y por tanto, por Apache Arrow como formato de datos en memoria.
Snippet Code (PySpark)
from pyspark.sql import SparkSession
from pyspark.sql.functions import col
# Create a Spark session using Spark Connect (remote Spark cluster)
spark = SparkSession.builder \
# .master("local[*]") \ # (Local) Uncomment for local mode
.remote("sc://remote-host:15002") \ # (Remote) Address of the remote Spark Connect server
.appName("RemotePySparkApp") \
.getOrCreate()
# Example: read a Parquet file
df = spark.read.parquet("/data/users.parquet")
# Perform a basic transformation
df.filter(col("age") > 30).select("name", "email").show(truncate=False)
# Stop the Spark session
spark.stop()
Snippet Code (Sail)
from pyspark.sql import SparkSession
from pyspark.sql.functions import col
# Create a Spark session using Spark Connect (remote Spark cluster)
spark = SparkSession.builder \
.remote("sc://remote-host:50051") \ # (Remote) Address of the remote Sail server
.appName("RemotePySparkApp") \
.getOrCreate()
# Example: read a Parquet file
df = spark.read.parquet("/data/users.parquet")
# Perform a basic transformation
df.filter(col("age") > 30).select("name", "email").show(truncate=False)
# Stop the Spark session
spark.stop()
El puerto es configurable, podría ser el mismo
De esta forma, se eliminan muchos de los costes asociados al stack tradicional: no hace falta un clúster Spark, ni JVM, ni procesos de serialización complejos.
El resultado: aplicaciones mucho más ligeras, rápidas, sin garbage collector, sin latencias por inicialización, y con un consumo mínimo de recursos, todo gracias a un motor escrito en Rust y ejecutado íntegramente en memoria.
Además, el equipo de Sail ha publicado benchmarks oficiales que comparan el rendimiento de sus consultas frente a Spark, mostrando mejoras notables en tiempos de ejecución y eficiencia general.
Mi apuesta para el futuro del data engineering #
Ya lo he comentado en más de una ocasión por LinkedIn, pero no me canso de repetirlo: apuesto firmemente por Apache DataFusion y Sail como el próximo gran paso en la ingeniería del dato.
En un momento donde muchas empresas centran sus esfuerzos en plataformas como Databricks, es comprensible que lo hagan: al fin y al cabo, es la compañía que dio forma a Apache Spark y ofrece un ecosistema muy completo, con funcionalidades avanzadas y una comunidad consolidada. Sin embargo, como profesional técnico y observador crítico del sector, me preocupa que estemos perdiendo el foco.
¿Realmente necesitamos tanta infraestructura? #
Cada vez más veo cómo la comodidad y el hábito nos llevan a normalizar despliegues pesados: “Lanzo mi aplicación PySpark, total, tengo cores y máquinas… que corra.” Esta actitud, aunque práctica en el corto plazo, suele venir acompañada de sobrecostes, ineficiencias y una falsa sensación de escalabilidad saludable.
La optimización, como bien señalaron Ángel Álvarez Pascua y David López González en su doble meetup Rendimiento y Optimización en Spark , no se limita a ajustar el número de particiones o elegir el formato de archivo adecuado. La optimización ocurre en múltiples niveles: infraestructura, datos y, por qué no, en el framework mismo.
Hora de replantear nuestro stack #
Unpopular opinion: Apache DataFusion y Sail podrían (y quizás deberían) ser el futuro de la ingeniería del dato.
¿Por qué?
-
Están escritos en Rust: un lenguaje moderno, seguro y extremadamente rápido.
-
Diseñados para ejecución vectorizada, aprovechando de forma eficiente la arquitectura del hardware moderno.
-
Son ligeros, modulares y embebibles, rompiendo con la tradición de stacks monolíticos y pesados basados en la JVM.
Así como en su día pasamos de bases de datos relacionales a Spark buscando escalabilidad, tal vez ha llegado el momento de repensar nuevamente nuestro stack de datos.
Pasar de gigantes pesados basados en la JVM a soluciones diseñadas con principios modernos: velocidad, simplicidad y eficiencia.
No digo que Spark esté muerto, faltaria… ¡ni mucho menos!, pero sí creo que ya existe una alternativa viable para muchísimos casos de uso que no requieren desplegar un clúster completo para realizar transformaciones básicas o análisis exploratorios. Y esa alternativa se llama DataFusion. Y su trampolín hacia la adopción real, Sail.