Modern Data Stack: quelle place pour Spark ?

Furcy Pin
7 min readJan 25, 2022

--

(English version available here)

Il y a un an déjà, certains prédisaient que dbt allait un jour devenir encore plus grand que Spark, et l’année 2021 leur a donné raison: dbt-labs a enchainé les succès et la rumeur cours qu’une nouvelle levée de fonds se prépare pour une valorisation de 6 milliards de dollars. A ce rythme, ils auront tôt fait de rattraper Databricks qui atteignait les 38 milliards de dollars de valorisation en septembre 2021.

Pour autant, ce qui m’a le plus interpelé par rapport à Spark cette année, c’est de voir à quel point Spark est absent de quasiment tous les articles de la “nouvelle vague” sur la Modern Data Stack, centrée autour de 2 composants-clé:

  • un moteur SQL massivement parallèle (BigQuery, Redshift, Snowflake)
  • et … dbt

En amont: des outils E/L no-code (Fivetran, Stitch, Airbyte). En aval: des outils de BI (Tableau, Looker, Power BI, Metabase) et des outils de reverse ETL pour exporter la donnée vers des bases spécialisée (Customer Data Platforms et autres).

Il suffit de taper “Modern Data Stack” dans Google Images pour constater que toutes les entreprises du secteur proposent leur propre liste de technologies composant cette stack, généralement afin de s’inscrire elle-même dans cette liste.

Mais on constate également que cette Modern Data Stack se construit généralement sans Spark, et l’écosystème Databricks s’envisage plus comme une alternative à celle-ci. Bien sûr, on voit bien que Databricks en a conscience et, comme bien d’autres, cherche à rejoindre le petit cercle des moteurs SQL au centre de la stack: ils ont publié en décembre l’intégration de dbt-core avec Databricks ainsi que Databricks SQL.

Source: https://lakefs.io/thoughts-on-the-future-of-the-databricks-ecosystem/

Récemment, j’ai répondu sur les réseaux à quelqu’un d’une autre entreprise qui s’interrogeait si cela vaudrait le coût d’ajouter Spark à sa Modern Data Stack. Etant donné que mon équipe utilise à la fois pySpark, BigQuery, et (un peu) dbt, je réfléchis actuellement beaucoup à cette question. J’ai donc répondu avec une liste de points de comparaison qui alimentent ma réflection actuelle, et que je reprend ici:

Infrastructure: BigQuery est entièrement géré par Google, rien a faire. Spark est plus complexe à maitriser, mais ça tend à se simplifier (Spark en mode serverless est déjà dispo sur GCP et arrive sur Databricks)

Learning curve: Là encore, c’est plus facile de trouver/former des gens compétents sur BigQuery que sur Spark. Un conseil: préférer pySpark à Spark en Scala, Java, ou .Net. Python est plus simple d’accès et est déjà utilisé pour Airflow, par exemple. Selon moi, les seules raisons valable pour utiliser un autre langage que Python en Spark sont: “faire des choses très avancées en RDD” et “réutiliser du code Java de l’entreprise sans avoir à le recoder”

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

Organisation du code: dbt a montré la bonne voie sur comment bien organiser ses pipelines de transformation SQL (j’en sais quelque chose, j’ai développé de 2014 à 2017 un outil qui fait la même chose que dbt, mais pour Apache Hive). A ma connaissance, il n’y a pas encore d’outil qui fasse cela pour pySpark (dbt supporte spark-sql, mais pas pySpark dans son entier). C’est pour cela qu’on en a développé un en interne, et que j’espère l’open-sourcer un jour. Sans un tel outil, il est très facile de revenir aux mêmes mauvaises pratiques que dbt a permis de gommer.

Expressivité: J’adore SQL, encore plus BigQuery, mais je ne peux faire tout ce dont j’ai besoin avec seulement du SQL. Je pense également qu’utiliser des templates Jinja n’est pas la bonne solution: comme le dit si bien Maxime Beauchemin dans son article, on va produire des montagnes de templates SQL et YAML. Personnellement, je pense qu’il s’agit là de la même erreur qu’ont fait les premiers schedulers: le config-as-code reste très limité, et Airflow a retourné la balance en prouvant que le code-as-config (merci Python) marchait bien mieux. Certes, JINJA gomme une partie des problèmes de rigidité du config-as-code, mais je trouve JINJA très lourd et verbeux, peu lisible, et unit-tester du code jinja semble complexe.

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

Limitations du SQL: Comme Maxime Beauchemin, je pense (du moins, j’espère) que les choses s’amélioreront de ce coté quand BigQuery, Snowflake, Redshift ou autre fourniront une API DataFrame similaire à celle de pySpark. C’est d’ailleurs déjà fait pour Snowflake, qui a développé Snowpark, dont l’API DataFrame est très clairement calquée sur celle de Spark. J’ai récemment démarré un POC d’API Dataframe pour BigQuery, afin de montrer tout ce qu’on pourrait faire de plus grâce à cela (choses qu’on peut certes déjà faire avec des macro jinja, mais de manière peu élégante et difficile à maintenir).
Je reviendrais plus en détail sur ce POC dans un prochain article.

UDFs: Dans la veine des limitations du SQL: certaines logiques s’implémentent parfois beaucoup plus facilement avec des UDFs dans un autre langage que le SQL. En BigQuery les UDF doivent être écrites soit en SQL, soit en Javascript (!!!). Idem avec Snowflake avec Java en prime. Va demander à un Data Engineer/Analyst/Scientist qui fait du Python d’écrire du Javascript… PySpark nous permet de faire des UDFs Python, et j’attends impatiemment que BigQuery le permette aussi.

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

Extract-Load (E/L): Je suis assez surpris par le nombre de gens qui semblent utiliser des opérateurs Airflow custom pour faire de l’E/L plutôt que Spark. Je trouve que c’est un des plus gros points forts de Spark: il dispose d’un grand nombre de connecteurs pour lire/écrire depuis tout et n’importe quoi. Il est également capable de faire de la détéction automatique de schéma sur du json/xml sans se prendre la tête. Et comme l’a noté Ari Bajo, il est préférable de passer par un état central et d’avoir O(n) connecteurs plutôt que de faire des connecteurs pour chaque source/destination en mode O(n²). Spark permet de faire tout ça, et j’imagine que c’est bien moins cher en coût de fonctionnement qu’un Fivetran (mais il se peut que l’outil open-source Airbyte change la donne à ce niveau). Le coût de mise en place est certes plus élevé, mais une fois payé, le répliquer pour ajouter d’autres sources ne prend pas très longtemps. Autre avantage: Spark permet de faire à la fois l’ETL et le reverse-ETL.
Il est vrai que cela nécessite des développeurs là où un non-dev pourra utiliser une interface graphique. Mais j’ai aussi l’impression qu’un non-dev avec une interface sera moins capable d’investiguer/corriger les potentiels problèmes (mais je me trompe peut-être sur ce point).

Temps réél: Dans mon équipe on commence à utiliser pySpark pour des cas simples de temps-réel (ingestion de données brutes dans BigQuery), mais je maîtrise trop peu le sujet pour comparer ça aux autres alternatives (lambda functions et autres). On mentionnera que Spark permet de faire de l’exactly-once assez facilement, en mode micro-batch.

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

Conclusion

Pour résumer en un mot, je pense que ces considérations gravitent autour d’un point central, à savoir la plus grande force, mais aussi la plus grande faiblesse du langage SQL: sa simplicité. C’est la simplicité de SQL qui fait que les plateformes BigQuery et Snowflake sont si simples d’accès et que son adoption est si large, tout en évitant (en théorie) un vendor lock-in trop important. A l’inverse, cette simplicité est aussi son plus gros défaut, on atteint bien vite les limites du SQL, et les bonnes pratiques de développement sont plus difficiles à appliquer et moins répandues. Avec dbt et Jinja, on a pu gommer certains de ces défauts, mais je pense qu’il faudra aller plus loin, avec des DataFrames ou d’autres API, pour permettre de développer des transformations plus génériques, plus avancées, et mieux répondre à l’explosion des besoins de la Data.

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

Dans mon équipe, un des challenges principaux est qu’on a tendance à alterner entre pySpark et BigQuery pour bénéficier de ce que chaque outil a de mieux à offrir. Cela rend le data-lineage plus difficile, puisque dbt ne permet de visualiser que la partie BigQuery et notre “dbt for pySpark” interne ne permet de visualiser que la partie pySpark. A terme, j’espère que BigQuery ajoutera les features qui nous manquent par rapport à pySpark (API DataFrame, UDF Python), ce qui nous permettrait peut-être un jour de migrer nos transformations actuelles de pySpark vers BigQuery. Il ne nous resterait alors plus que l’E/L et le temps réel coté pySpark.

Quand je n’ai pas d’idée d’image pour illustrer un article de blog sur SQL, je cherche “xkcd sql” dans Google
Source: https://xkcd.com/1409/

--

--

Furcy Pin

[Available for freelance work] Data Engineer, Data Plumber, Data Librarian, Data Smithy.