1. Introduction
Dans cet atelier de programmation, vous allez explorer les fonctionnalités du data lakehouse unifié sur Google Cloud. Vous allez interagir avec des ensembles de données publics diffusés via le catalogue REST Apache Iceberg sur Lakehouse, puis appliquer les fonctionnalités d'IA de Google Cloud aux données structurées et non structurées.
Vous allez interroger l'ensemble de données classique sur les taxis de New York à l'aide d'Apache Iceberg, explorer la fonctionnalité temporelle pour auditer les modifications apportées aux données, puis utiliser BigQuery ML et Gemini pour exécuter des modèles d'IA sur vos données.
Objectifs de l'atelier
- Utilisez Managed Service pour Apache Spark pour interroger les ensembles de données publics Apache Iceberg hébergés sur Lakehouse.
- Interrogez des données structurées au format Apache Iceberg.
- Démontrer le voyage dans le temps dans Apache Iceberg.
- Utilisez BigQuery ML pour entraîner un modèle prédictif sur des données structurées.
- Créez une table d'objets Lakehouse (données non structurées) et utilisez Gemini pour analyser les images.
Prérequis
- Un navigateur Web tel que Chrome.
- Un projet Google Cloud avec facturation activée.
Coût et durée attendus
- Durée : environ 45 minutes.
- Coût estimé : moins de 2 $. Nous utilisons des ensembles de données publics et des requêtes sans serveur pour maintenir les coûts à un niveau bas.
2. Préparation
Dans cette étape, vous allez préparer votre environnement et activer les API nécessaires.
Démarrer Cloud Shell
Vous exécuterez la plupart des commandes à partir de Google Cloud Shell.
- Cliquez sur Activer Cloud Shell en haut de la console Google Cloud.
- Vérifiez l'authentification :
gcloud auth list - Confirmez votre projet :
gcloud config get project - Si le projet n'est pas défini, définissez-le à l'aide de votre ID de projet :
gcloud config set project <YOUR_PROJECT_ID>
Activer les API
Exécutez la commande suivante pour activer les API requises pour BigQuery, Cloud Resource Manager et Gemini Enterprise Agent Engine :
gcloud services enable \
bigquery.googleapis.com \
aiplatform.googleapis.com \
cloudresourcemanager.googleapis.com
Configurer l'environnement et créer un bucket de dépendances
- Définissez vos variables d'environnement dans votre terminal :
export PROJECT_ID=$(gcloud config get project) export REGION=us-central1 export DEPS_BUCKET=$PROJECT_ID-deps-bucket - Créez le bucket Cloud Storage des dépendances. Les scripts PySpark sont importés ici au moment de l'envoi du job :
gcloud storage buckets create gs://$DEPS_BUCKET --location=$REGION
3. Se connecter au catalogue public Apache Iceberg
Dans cette étape, vous allez vous connecter à un catalogue Apache Iceberg de production hébergé sur le lakehouse Google Cloud.
Exécuter Spark SQL avec la CLI Managed Apache Spark Batch
Nous utiliserons Managed Service pour Apache Spark pour exécuter des jobs PySpark sans avoir à gérer l'infrastructure. Nous le configurerons pour qu'il pointe vers le catalogue REST Lakehouse public.
- Définissez les propriétés du catalogue REST Lakehouse pour éviter de les répéter.Cette configuration indique à Spark :
- Pour utiliser les bibliothèques
iceberg-spark-runtimeeticeberg-gcp-bundle. - Pour configurer un catalogue nommé
my_catalogà l'aide du point de terminaison du catalogue REST Lakehouse. - Pour utiliser Google Cloud Storage (GCS) pour lire les fichiers de données au lieu du système de fichiers local par défaut.
- Définissez ce catalogue
my_catalogcomme par défaut pour notre session. - Utiliser des identifiants fournis pour renforcer la sécurité et simplifier l'accès aux données.
export METASTORE_PROPERTIES="^|^spark.jars.packages=org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.10.0,org.apache.iceberg:iceberg-gcp-bundle:1.10.0|\ spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog|\ spark.sql.catalog.my_catalog.type=rest|\ spark.sql.catalog.my_catalog.uri=https://biglake.googleapis.com/iceberg/v1/restcatalog|\ spark.sql.catalog.my_catalog.warehouse=gs://biglake-public-nyc-taxi-iceberg|\ spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.gcp.gcs.GCSFileIO|\ spark.sql.catalog.my_catalog.header.x-goog-user-project=$PROJECT_ID|\ spark.sql.catalog.my_catalog.header.X-Iceberg-Access-Delegation=vended-credentials|\ spark.sql.catalog.my_catalog.rest.auth.type=org.apache.iceberg.gcp.auth.GoogleAuthManager|\ spark.sql.defaultCatalog=my_catalog|\ spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions|\ spark.log.level=ERROR" - Pour utiliser les bibliothèques
- Créez un fichier de requête de test simple :
cat <<EOF > test.py from pyspark.sql import SparkSession spark = SparkSession.builder.getOrCreate() spark.sql("SHOW TABLES IN public_data").show() EOF - Envoyez le job par lot :
Attendez quelques minutes que le job par lot se termine.Une fois le job terminé, un résultat semblable à celui-ci devrait s'afficher :gcloud dataproc batches submit pyspark \ --project=$PROJECT_ID \ --region=$REGION \ --version=2.3 \ --properties="$METASTORE_PROPERTIES" \ --deps-bucket=gs://$DEPS_BUCKET \ test.py+-----------+----------------+-----------+ | namespace| tableName|isTemporary| +-----------+----------------+-----------+ |public_data| nyc_taxicab| false| |public_data|nyc_taxicab_2021| false| +-----------+----------------+-----------+
4. Interroger des données Iceberg structurées
Une fois connecté, vous disposez d'un accès SQL complet aux ensembles de données. Nous allons interroger l'ensemble de données sur les taxis new-yorkais modélisé sous forme de table Iceberg.
Exécuter une requête d'agrégation standard
Créez un fichier nommé query.py :
cat <<EOF > query.py
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
query = """
SELECT
passenger_count,
COUNT(1) AS num_trips,
ROUND(AVG(total_amount), 2) AS avg_fare,
ROUND(AVG(trip_distance), 2) AS avg_distance
FROM public_data.nyc_taxicab
WHERE data_file_year = 2021 AND passenger_count > 0
GROUP BY passenger_count
ORDER BY num_trips DESC
"""
spark.sql(query).show()
EOF
Envoyez-le à l'aide de Managed Service pour Apache Spark :
gcloud dataproc batches submit pyspark \
--project=$PROJECT_ID \
--region=$REGION \
--version=2.3 \
--properties="$METASTORE_PROPERTIES" \
--deps-bucket=gs://$DEPS_BUCKET \
query.py
Attendez quelques minutes que le job par lot finisse de s'exécuter.
Une fois le job terminé, un résultat semblable à celui-ci devrait s'afficher :
+---------------+---------+--------+------------+ |passenger_count|num_trips|avg_fare|avg_distance| +---------------+---------+--------+------------+ | 1| 21508009| 18.82| 3.03| | 2| 4424746| 20.22| 3.40| | 3| 1164846| 19.84| 3.27| | 5| 718282| 18.88| 3.07| | 4| 466485| 20.61| 3.44| | 6| 452467| 18.97| 3.11| | 7| 78| 65.24| 3.71| | 8| 49| 57.39| 5.88| | 9| 35| 73.26| 6.20| | 96| 1| 17.00| 2.00| | 112| 1| 15.00| 2.00| +---------------+---------+--------+------------+
Pourquoi utiliser Apache Iceberg ?
- Élimination des partitions : la requête filtre sur
data_file_year = 2021. Iceberg permet au moteur d'ignorer complètement l'analyse des données des autres années. - Agilité du moteur : vous pouvez exécuter cette requête dans Spark, Trino ou BigQuery sans copier les données.
5. Voyage temporel dans Apache Iceberg
L'une des fonctionnalités les plus puissantes d'Iceberg est Time Travel. Il vous permet d'interroger les données telles qu'elles existaient dans une version ou un instantané antérieur.
Afficher l'historique des tableaux
Créez un fichier nommé history.py :
cat <<EOF > history.py
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
spark.sql("SELECT * FROM public_data.nyc_taxicab.history").show()
EOF
Envoyez-le :
gcloud dataproc batches submit pyspark \
--project=$PROJECT_ID \
--region=$REGION \
--version=2.3 \
--properties="$METASTORE_PROPERTIES" \
--deps-bucket=gs://$DEPS_BUCKET \
history.py
Le résultat obtenu dans la console doit ressembler à ceci :
+--------------------+-------------------+-------------------+-------------------+ | made_current_at| snapshot_id| parent_id|is_current_ancestor| +--------------------+-------------------+-------------------+-------------------+ |2026-01-07 21:32:...|6333415779680505547| NULL| true| |2026-01-07 21:34:...|1840345522877675925|6333415779680505547| true| |2026-01-07 21:36:...|7203554539964460256|1840345522877675925| true| |2026-01-07 21:38:...|4573466015237516024|7203554539964460256| true| |2026-01-07 21:40:...|3353190952148867790|4573466015237516024| true| |2026-01-07 21:42:...|1335547378580631681|3353190952148867790| true| |2026-01-07 21:44:...|8203141258229894239|1335547378580631681| true| |2026-01-07 21:46:...|1597048231706307813|8203141258229894239| true| |2026-01-07 21:48:...|6247811509231462655|1597048231706307813| true| |2026-01-07 21:50:...|2527184310045633322|6247811509231462655| true| |2026-01-07 21:52:...|2512764101237223642|2527184310045633322| true| |2026-01-07 21:52:...|7045957533358062548|2512764101237223642| true| |2026-01-07 21:53:...| 531753237516076726|7045957533358062548| true| |2026-01-07 21:53:...|4184653573199718274| 531753237516076726| true| |2026-01-07 21:54:...|5125223829492177301|4184653573199718274| true| |2026-01-07 21:54:...|6844673237417600305|5125223829492177301| true| |2026-01-07 21:54:...|6634828203344518093|6844673237417600305| true| |2026-01-07 21:55:...|7637728273407236194|6634828203344518093| true| |2026-01-07 21:55:...|3424071684958740192|7637728273407236194| true| |2026-01-07 21:55:...|1743746294196424254|3424071684958740192| true| +--------------------+-------------------+-------------------+-------------------+
Vous verrez des lignes représentant différents ID d'instantanés et la date à laquelle ils ont été validés.
Comparer le nombre de lignes actuel à celui d'une période précédente
Créez un fichier nommé timetravel.py :
cat <<EOF > timetravel.py
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
query = """
SELECT 'Current State' AS version, COUNT(*) AS count FROM public_data.nyc_taxicab
UNION ALL
SELECT 'Past State' AS version, COUNT(*) AS count FROM public_data.nyc_taxicab VERSION AS OF 4573466015237516024
"""
spark.sql(query).show()
EOF
Envoyez-le :
gcloud dataproc batches submit pyspark \
--project=$PROJECT_ID \
--region=$REGION \
--version=2.3 \
--properties="$METASTORE_PROPERTIES" \
--deps-bucket=gs://$DEPS_BUCKET \
timetravel.py
Le résultat obtenu dans la console doit ressembler à ceci :
+-------------+----------+ | version| count| +-------------+----------+ |Current State|1293069366| | Past State| 72878594| +-------------+----------+
Vous pouvez ainsi auditer les modifications apportées aux données au fil du temps.
6. IA structurée avec BigQuery ML
Maintenant que vous avez exploré les données Iceberg, utilisons les fonctionnalités d'IA de BigQuery. Étant donné que le catalogue Iceberg public est en lecture seule, nous pouvons utiliser BigQuery pour entraîner un modèle dans notre espace de travail en lisant les tables publiques.
Créer un ensemble de données local
Commencez par créer un ensemble de données dans votre projet pour stocker le modèle d'IA à l'aide de la CLI bq :
bq mk --location=$REGION --project_id=$PROJECT_ID iceberg_ai
Entraîner un modèle de régression linéaire
Vous allez maintenant entraîner un modèle de régression linéaire à l'aide de la table Iceberg Lakehouse publique.
Créez un fichier de requête et entraînez le modèle à l'aide de bq query :
cat <<'EOF' > train_model.sql
CREATE OR REPLACE MODEL `iceberg_ai.predict_fare`
OPTIONS(model_type='LINEAR_REG', input_label_cols=['fare_amount']) AS
SELECT fare_amount, passenger_count, CAST(trip_distance AS FLOAT64) AS trip_distance
FROM `bigquery-public-data`.`biglake-public-nyc-taxi-iceberg`.public_data.nyc_taxicab
WHERE fare_amount > 0 AND trip_distance > 0 AND RAND() < 0.01; -- Using 1% of data to downsample
EOF
bq query --location=$REGION --use_legacy_sql=false < train_model.sql
Effectuer des prédictions à l'aide du modèle
Maintenant que le modèle est entraîné, vous pouvez l'utiliser pour prédire les montants des courses pour de nouveaux trajets à l'aide de ML.PREDICT.
Créez un fichier de requête et exécutez la prédiction à l'aide de bq query :
cat <<'EOF' > predict_fare.sql
SELECT
predicted_fare_amount, passenger_count, trip_distance
FROM
ML.PREDICT(MODEL `iceberg_ai.predict_fare`,
(
SELECT 2 AS passenger_count, 5.0 AS trip_distance
)
);
EOF
bq query --location=$REGION --use_legacy_sql=false < predict_fare.sql
La sortie obtenue doit ressembler à ceci :
+-----------------------+-----------------+---------------+ | predicted_fare_amount | passenger_count | trip_distance | +-----------------------+-----------------+---------------+ | 14.12252095150709 | 2 | 5.0 | +-----------------------+-----------------+---------------+
7. IA non structurée avec Lakehouse
Les données ne se limitent pas aux lignes et aux colonnes. Les data lakehouses unifiés gèrent également les données non structurées (images, PDF). Utilisons les tables d'objets et les références d'objets pour interroger les données non structurées.
Les tables d'objets sont des tables externes en lecture seule dans BigQuery qui listent les objets d'un chemin Cloud Storage. Chaque ligne représente un fichier, avec des colonnes pour les métadonnées telles que uri et size, ainsi qu'une colonne spéciale ref contenant le ObjectRef.
Les références d'objet (ObjectRef) pointent vers les données réelles d'un seul fichier. Les fonctions BigQuery ML modernes (comme AI.GENERATE ou AI.AGG) consomment ObjectRef pour lire le contenu des fichiers (images, audio ou texte) à des fins d'analyse sans charger les octets dans une table standard.
Créer un ensemble de données pour l'IA non structurée
Commencez par créer un deuxième ensemble de données dans votre projet pour stocker les tables d'objets à l'aide de la CLI bq dans la région multirégionale US :
bq mk --location=US --project_id=$PROJECT_ID iceberg_object_ai
Créer une connexion externe
Pour interroger des données stockées dans Cloud Storage (tables d'objets et données non structurées) à partir de BigQuery, vous devez créer une connexion externe.
Exécutez la commande suivante dans Cloud Shell pour créer une connexion à une ressource cloud :
bq mk --connection --project_id=$PROJECT_ID --location=US --connection_type=CLOUD_RESOURCE my-conn
Recherchez l'ID du compte de service créé pour votre connexion :
CONNECTION_SA=$(bq show --format=json --project_id=$PROJECT_ID --connection $PROJECT_ID.us.my-conn | jq -r '.serviceAccountId // .cloudResource.serviceAccountId')
Attribuez les rôles Utilisateur du moteur d'agents Gemini Enterprise et Lecteur des objets de l'espace de stockage au compte de service afin qu'il puisse appeler les modèles Gemini et lire les données GCS :
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CONNECTION_SA" \
--role="roles/aiplatform.user"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CONNECTION_SA" \
--role="roles/storage.objectViewer"
Créer une table d'objets
Nous allons utiliser la connexion externe my-conn créée dans la section précédente pour accéder aux données non structurées. Créez un fichier de requête et la table d'objets à l'aide de bq query :
cat <<'EOF' > create_object_table.sql
CREATE EXTERNAL TABLE `iceberg_object_ai.sample_images`
WITH CONNECTION `us.my-conn`
OPTIONS (
object_metadata = 'SIMPLE',
uris = ['gs://cloud-samples-data/vision/landmark/*']
);
EOF
bq query --use_legacy_sql=false < create_object_table.sql
Utiliser Gemini sur les données d'objet
Exécutez maintenant une requête à l'aide de Gemini pour évaluer les images sans les télécharger.
Interrogez les images à l'aide du langage SQL standard via bq query :
cat <<EOF > query_images.sql
SELECT
uri,
image_analysis.description
FROM (
SELECT
uri,
AI.GENERATE(
(
'Identify what is happening in the image.',
ref
),
connection_id => 'us.my-conn',
endpoint => 'gemini-2.5-flash-lite',
output_schema => 'event STRING, severity STRING, description STRING'
) AS image_analysis
FROM
iceberg_object_ai.sample_images
);
EOF
bq query --use_legacy_sql=false < query_images.sql
Exemple de résultat :
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| uri | description |
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| gs://cloud-samples-data/vision/landmark/eiffel_tower.jpg | The Eiffel Tower stands tall against a cloudy sky, overlooking the Seine River in Paris. Boats are docked along the riverbank, and trees line the opposite shore, with bridges and buildings visible in the distance. |
| gs://cloud-samples-data/vision/landmark/pofa.jpg | A wide shot shows the Palace of Fine Arts, a monumental structure in San Francisco, California. The building features a large rotunda with a dome, surrounded by colonnades. In front of the rotunda is a lagoon. Several people are walking around the grounds. The sky is blue with a few scattered clouds. |
| gs://cloud-samples-data/vision/landmark/st_basils.jpeg | A monument stands in front of Saint Basil's Cathedral in Moscow under a bright blue sky with scattered white clouds. The cathedral features distinctive onion domes in various colors and patterns, including red, blue and white stripes, green and beige stripes, and red and blue diamonds. A large green tree partially obscures the left side of the cathedral. People are visible in the foreground near the base of the monument and the cathedral entrance. |
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Explorer directement les ObjectRefs : analyse des sentiments
Bien que les tables d'objets gèrent automatiquement les références de fichiers, vous pouvez interagir directement avec ces objets à l'aide des références d'objets BigQuery pour exécuter des analyses à la volée sur des fichiers individuels.
Par exemple, vous pouvez utiliser un petit fichier texte stocké dans votre propre bucket GCS (à l'aide de la variable $DEPS_BUCKET créée précédemment) et l'analyser à l'aide de OBJ.MAKE_REF avec bq query.
Commencez par créer un petit fichier texte et importez-le dans votre bucket :
cat <<'EOF' > review.txt
This product is fantastic! It exceeded my expectations. The quality is top-notch. I highly recommend it to everyone!
EOF
gcloud storage cp review.txt gs://${DEPS_BUCKET}/review.txt
Interrogez maintenant le fichier à l'aide de OBJ.MAKE_REF dans le langage SQL standard :
cat <<EOF > sentiment_analysis.sql
SELECT
AI.GENERATE(
(
'Analyze the sentiment of this text file. Is it positive, negative, or neutral? Explain why.',
OBJ.MAKE_REF('gs://${DEPS_BUCKET}/review.txt', 'us.my-conn')
),
connection_id => 'us.my-conn',
endpoint => 'gemini-2.5-flash-lite'
).result AS ml_generate_text_result;
EOF
bq query --use_legacy_sql=false < sentiment_analysis.sql
Exemple de résultat :
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ml_generate_text_result |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| This text file has a **strongly positive** sentiment. |
| |
| Here's why: |
| |
| * **Positive Keywords:** The text is filled with unequivocally positive words and phrases: |
| * "fantastic" |
| * "exceeded my expectations" |
| * "top-notch" |
| * "highly recommend" |
| |
| * **Enthusiastic Language:** The use of exclamation marks ("!") further amplifies the positive tone, indicating excitement and strong approval. |
| |
| * **Lack of Negative or Neutral Elements:** There are no words, phrases, or implications that suggest any dissatisfaction, criticism, or even indifference. |
| |
| In summary, the author's language is enthusiastic and uses multiple strong positive descriptors, leaving no room for doubt that their opinion of the product is overwhelmingly positive. |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
8. Effectuer un nettoyage
Pour éviter que les ressources créées lors de cet atelier de programmation soient facturées en permanence sur votre compte Google Cloud, supprimez-les.
Supprimer l'ensemble de données et la connexion
Exécutez la commande suivante dans Cloud Shell pour supprimer vos ensembles de données et votre connexion :
bq rm -r -f --location=$REGION iceberg_ai
bq rm -r -f --location=US iceberg_object_ai
bq rm --connection $PROJECT_ID.US.my-conn
Supprimer les buckets GCS et les fichiers locaux
Libérez de l'espace dans les buckets GCS et les fichiers locaux :
# Delete GCS buckets
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud storage rm -r gs://dataproc-temp-${REGION}-${PROJECT_NUMBER}-*
gcloud storage rm -r gs://dataproc-staging-${REGION}-${PROJECT_NUMBER}-*
gcloud storage rm -r gs://${DEPS_BUCKET}
# Delete local files
rm -f train_model.sql predict_fare.sql create_object_table.sql query_images.sql sentiment_analysis.sql test.py query.py history.py timetravel.py review.txt
Vous pouvez également supprimer l'intégralité du projet si vous l'avez créé uniquement pour cet atelier.
9. Félicitations
Félicitations ! Vous avez créé un data lakehouse unifié à l'aide d'Apache Iceberg, Lakehouse et BigQuery AI.
Connaissances acquises
- Découvrez comment vous connecter à des catalogues REST Apache Iceberg publics et les interroger.
- Utiliser la fonctionnalité temporelle dans Iceberg pour auditer les versions de l'ensemble de données.
- Entraînement de modèles BigQuery ML sur des données structurées.
- Connecter des données non structurées (images) à l'aide de tables d'objets et d'ObjectRef.
- Utiliser Gemini directement dans BigQuery SQL pour analyser des images.