L’image Superset est personnalisée pour inclure les pilotes Snowflake et ClickHouse.
Lors de la première exécution, utilisez --build afin que Docker la construise :
cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake/superset"source ../.envdocker compose up -d --build
Tous les graphiques utilisent des jeux de données virtuels : des requêtes SQL
enregistrées sous un nom.
Pour créer chaque jeu de données :
Ouvrez Datasets → + Dataset.
Sélectionnez la base NYC Taxi — Snowflake (Source).
Cliquez sur Create dataset from SQL query, puis collez le SQL ci-dessous.
Enregistrez-le sous le nom indiqué.
Après l’enregistrement, ouvrez Datasets → icône en forme de crayon → onglet
Columns → "Sync columns from source" → Save. Sans cette étape, le générateur de
graphiques affiche zéro colonne.
SELECT DATE_TRUNC('hour', pickup_at) AS hour_bucket, pickup_borough, COUNT(*) AS trip_count, SUM(total_amount_usd) AS total_revenue, AVG(tip_amount_usd / NULLIF(fare_amount_usd, 0)) AS avg_tip_rate, AVG(trip_distance_miles) AS avg_distance_milesFROM ANALYTICS.FACT_TRIPSWHERE pickup_at >= DATEADD('day', -7, CURRENT_TIMESTAMP()) AND pickup_borough IS NOT NULLGROUP BY 1, 2ORDER BY 1 DESC, total_revenue DESC
SELECT pickup_at::DATE AS trip_date, COUNT(*) AS daily_trip_count, AVG(trip_distance_miles) AS daily_avg_distance, AVG(AVG(trip_distance_miles)) OVER ( ORDER BY pickup_at::DATE ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ) AS rolling_7d_avg_distance, SUM(total_amount_usd) AS daily_revenue, SUM(SUM(total_amount_usd)) OVER ( ORDER BY pickup_at::DATE ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ) AS rolling_7d_revenueFROM ANALYTICS.FACT_TRIPSGROUP BY 1ORDER BY 1 DESCLIMIT 365
SELECT CASE WHEN surge_multiplier >= 2.0 THEN 'High Surge (2x+)' WHEN surge_multiplier >= 1.5 THEN 'Medium Surge (1.5–2x)' WHEN surge_multiplier > 1.0 THEN 'Low Surge (1–1.5x)' ELSE 'No Surge (1x)' END AS surge_category, COUNT(*) AS trip_count, ROUND(AVG(total_amount_usd), 2) AS avg_total_fare, ROUND(AVG(fare_amount_usd), 2) AS avg_base_fare, ROUND(AVG(surge_multiplier), 2) AS avg_surgeFROM ANALYTICS.FACT_TRIPSWHERE surge_multiplier IS NOT NULLGROUP BY 1ORDER BY avg_surge DESC
Schéma : RAW ← modifiez cette valeur lors de la création du jeu de données
Interroge directement RAW.TRIPS_RAW à l’aide de la syntaxe de chemin avec
deux-points de VARIANT. Cette requête est volontairement lente et sert de cible au
benchmark ClickHouse.
SELECT ROUND(TRIP_METADATA:driver.rating::FLOAT, 1) AS rating_bucket, COUNT(*) AS trip_count, ROUND(AVG(TOTAL_AMOUNT), 2) AS avg_fare, ROUND(AVG(DATEDIFF('minute', PICKUP_DATETIME, DROPOFF_DATETIME)), 1) AS avg_duration_minutesFROM RAW.TRIPS_RAWWHERE TRIP_METADATA:driver IS NOT NULL AND TRIP_METADATA:driver.rating IS NOT NULLGROUP BY 1ORDER BY 1
SELECT vehicle_type, COUNT(*) AS trip_count, SUM(total_amount_usd) AS total_revenue, AVG(total_amount_usd) AS avg_fare, AVG(trip_distance_miles) AS avg_distanceFROM ANALYTICS.FACT_TRIPSWHERE vehicle_type IS NOT NULLGROUP BY 1ORDER BY total_revenue DESC
SELECT traffic_level, COUNT(*) AS trip_count, AVG(duration_minutes) AS avg_duration_minutes, AVG(trip_distance_miles) AS avg_distance_miles, AVG(total_amount_usd) AS avg_fareFROM ANALYTICS.FACT_TRIPSWHERE traffic_level IS NOT NULLGROUP BY 1ORDER BY avg_duration_minutes DESC
SELECT pickup_at::DATE AS trip_date, app_platform, COUNT(*) AS trip_count, AVG(surge_multiplier) AS avg_surgeFROM ANALYTICS.FACT_TRIPSWHERE app_platform IS NOT NULL AND pickup_at >= DATEADD('day', -30, CURRENT_TIMESTAMP())GROUP BY 1, 2ORDER BY 1 DESC
Objectif : fournir une vue opérationnelle en temps réel des sept derniers jours.
Dans la deuxième partie, c’est le premier tableau de bord que les partenaires redirigent
vers ClickHouse.
Créer le tableau de bord :
Dashboards → + Dashboard
Titre : Operations Command Center
Actualisation automatique toutes les 15 minutes avec
··· → Edit dashboard → Auto-refresh
[ Total Trips — Big Number ] [ Total Revenue — Big Number (add 2nd) ][ Trips per Hour — Line chart (full width) ][ Revenue by Borough — Bar ] [ Payment Type Split — Pie ][ Borough Performance — Table (full width) ]
Objectif : fournir une vue stratégique pour la revue hebdomadaire de l’activité.
Il met en évidence les fonctions de fenêtrage et la syntaxe propre à Snowflake,
QUALIFY, qu’il faut réécrire dans ClickHouse.
Objectif : analyser en profondeur les performances des conducteurs et la qualité
des trajets. Il s’agit volontairement du tableau de bord le plus lent : il interroge
directement RAW.TRIPS_RAW avec un accès VARIANT. Consignez ici la durée de la requête
afin d’établir la valeur de référence du benchmark de performances ClickHouse de la
deuxième partie.
[ Trip Count by Rating — Bar ] [ Avg Fare by Rating — Line ][ Revenue by Vehicle Type — Horizontal bar (full width) ][ Traffic Level Impact — Bar (50%) ] [ Surge by Platform — Table (50%)][ Daily Trips by Platform — Line chart (full width) ]
Ouvrez chaque tableau de bord et vérifiez que tous les graphiques se chargent sans
erreur.
Pour le troisième tableau de bord, relevez la durée d’exécution de la requête
dqa_rating_dist dans Snowflake UI → Activity → Query History, puis conservez-la
comme référence pour le benchmark de migration.
Importation automatique (./init_superset.sh) — fonctionne sans modification.
Le script enregistre la véritable connexion Snowflake à partir de .envavant
l’importation, puis réapplique l’URI correcte après chaque importation, dans
_update_db de init_superset.sh. Les valeurs fictives sont donc remplacées par
vos véritables identifiants.
Importation manuelle dans l’interface Superset — la base importée est créée avec
l’URI fictive et ne peut pas se connecter. Après l’importation, ouvrez
Settings → Database Connections → Edit, puis remplacez sqlalchemy_uri par
votre véritable URI Snowflake, par exemple
snowflake://<USER>:<PASSWORD>@<ORG>-<ACCOUNT>/NYC_TAXI_DB/ANALYTICS?role=ANALYST_ROLE&warehouse=ANALYTICS_WH.
Nouvelle exportation de vos propres tableaux de bord — Superset inscrit votre
localisateur de compte et votre nom d’utilisateur dans databases/*.yaml. Avant
d’ajouter les fichiers ZIP réexportés au dépôt, remplacez ces valeurs par
MYORG-MYACCOUNT / LAB_USER afin de ne pas divulguer vos identifiants de compte
dans l’historique git.