Creazione di una data lakehouse unificata per l'AI con Apache Iceberg e BigLake

1. Introduzione

In questo codelab, esplorerai le funzionalità della data lakehouse unificata su Google Cloud. Interagirai con i set di dati pubblici forniti tramite il catalogo REST di Apache Iceberg su BigLake e poi applicherai le funzionalità di AI di Google Cloud ai dati strutturati e non strutturati.

Eseguirai query sul set di dati NYC Taxi classico utilizzando Apache Iceberg, approfondirai il Time Travel per controllare le modifiche ai dati e poi utilizzerai BigQuery ML e Gemini per eseguire modelli di AI sui tuoi dati.

In questo lab proverai a:

  • Utilizzare Google Cloud Serverless per Apache Spark per eseguire query sui set di dati pubblici di Apache Iceberg ospitati su BigLake.
  • Eseguire query sui dati strutturati in formato Apache Iceberg.
  • Dimostrare il Time Travel in Apache Iceberg.
  • Utilizzare BigQuery ML per addestrare un modello predittivo sui dati strutturati.
  • Creare una tabella di oggetti BigLake (dati non strutturati) e utilizzare Gemini per analizzare le immagini.

Che cosa ti serve

  • Un browser web come Chrome.
  • Un progetto Google Cloud con la fatturazione abilitata.

Costo e durata previsti

  • Tempo per il completamento: circa 45 minuti.
  • Costo stimato: < 2,00 $. Utilizziamo set di dati pubblici e query serverless per mantenere bassi i costi.

2. Configurazione e requisiti

In questo passaggio, preparerai l'ambiente e abiliterai le API necessarie.

Avvia Cloud Shell

Eseguirai la maggior parte dei comandi da Google Cloud Shell.

  1. Fai clic su Attiva Cloud Shell nella parte superiore della console Google Cloud.
  2. Verifica l'autenticazione:
    gcloud auth list
    
  3. Conferma il progetto:
    gcloud config get project
    
  4. Se il progetto non è impostato, impostalo utilizzando l'ID progetto:
    gcloud config set project <YOUR_PROJECT_ID>
    

Abilita API

Esegui il comando seguente per abilitare le API richieste per BigQuery, Cloud Resource Manager e Vertex AI:

gcloud services enable \
  bigquery.googleapis.com \
  aiplatform.googleapis.com \
  cloudresourcemanager.googleapis.com

Configura l'ambiente e crea il bucket delle dipendenze

  1. Imposta le variabili di ambiente nel terminale:
    export PROJECT_ID=$(gcloud config get project)
    export REGION=us-central1
    export DEPS_BUCKET=$PROJECT_ID-deps-bucket
    
  2. Crea il bucket Cloud Storage delle dipendenze. Gli script PySpark vengono caricati qui al momento dell'invio del job:
    gcloud storage buckets create gs://$DEPS_BUCKET --location=$REGION
    

3. Connettiti al catalogo pubblico di Apache Iceberg

In questo passaggio, ti connetterai a un catalogo Apache Iceberg live e di livello di produzione ospitato su BigLake di Google Cloud.

Esegui Spark SQL con l'interfaccia a riga di comando batch di Serverless per Apache Spark

Utilizzeremo Google Cloud Serverless per Apache Spark per eseguire job PySpark senza dover gestire l'infrastruttura. Lo configureremo in modo che punti al catalogo REST pubblico di BigLake.

  1. Definisci le proprietà del catalogo REST di BigLake per evitare di ripeterle.Questa configurazione indica a Spark:
    • Utilizzare le librerie iceberg-spark-runttime e iceberg-gcp-bundle.
    • Configurare un catalogo denominato my_catalog utilizzando l'endpoint del catalogo REST di BigLake.
    • Utilizzare Google Cloud Storage (GCS) per leggere i file di dati anziché il file system locale predefinito.
    • Impostare questo catalogo my_catalog come predefinito per la nostra sessione.
    • Utilizzare le credenziali vendute per una maggiore sicurezza e un accesso ai dati semplificato.
    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"
    
  2. Crea un semplice file di query di test:
    cat <<EOF > test.py
    from pyspark.sql import SparkSession
    
    spark = SparkSession.builder.getOrCreate()
    
    spark.sql("SHOW TABLES IN public_data").show()
    EOF
    
  3. Invia il job batch:
    gcloud dataproc batches submit pyspark \
      --project=$PROJECT_ID \
      --region=$REGION \
      --version=2.3 \
      --properties="$METASTORE_PROPERTIES" \
      --deps-bucket=gs://$DEPS_BUCKET \
      test.py
    
    Dovresti vedere un output simile al seguente:
    +-----------+----------------+-----------+
    |  namespace|       tableName|isTemporary|
    +-----------+----------------+-----------+
    |public_data|     nyc_taxicab|      false|
    |public_data|nyc_taxicab_2021|      false|
    +-----------+----------------+-----------+
    

4. Esegui query sui dati Iceberg strutturati

Una volta connesso, hai accesso SQL completo ai set di dati. Eseguiremo query sul set di dati NYC Taxi modellato come tabella Iceberg.

Esegui una query di aggregazione standard

Crea un file denominato 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

E invialo utilizzando Serverless per 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

Dovresti vedere un output simile a questo nella console:

+---------------+---------+--------+------------+
|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|
+---------------+---------+--------+------------+

Perché utilizzare Apache Iceberg qui?

  • Eliminazione delle partizioni: la query filtra su data_file_year = 2021. Iceberg consente al motore di saltare completamente la scansione dei dati di altri anni.
  • Agilità del motore: puoi eseguire questa operazione in Spark, Trino o BigQuery senza copiare i dati.

5. Time Travel in Apache Iceberg

Una delle funzionalità più potenti di Iceberg è Time Travel. Ti consente di eseguire query sui dati così come esistevano in una versione o in uno snapshot precedente.

Visualizza la cronologia delle tabelle

Crea un file denominato 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

E invialo:

gcloud dataproc batches submit pyspark \
  --project=$PROJECT_ID \
  --region=$REGION \
  --version=2.3 \
  --properties="$METASTORE_PROPERTIES" \
  --deps-bucket=gs://$DEPS_BUCKET \
  history.py

Dovresti vedere un output simile al seguente nella console:

+--------------------+-------------------+-------------------+-------------------+
|     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|
+--------------------+-------------------+-------------------+-------------------+

Vedrai righe che rappresentano diversi ID snapshot e quando sono stati sottoposti a commit.

Confronta il conteggio delle righe attuale e precedente

Crea un file denominato 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

E invialo:

gcloud dataproc batches submit pyspark \
  --project=$PROJECT_ID \
  --region=$REGION \
  --version=2.3 \
  --properties="$METASTORE_PROPERTIES" \
  --deps-bucket=gs://$DEPS_BUCKET \
  timetravel.py

Dovresti vedere un output simile al seguente nella console:

+-------------+----------+
|      version|     count|
+-------------+----------+
|Current State|1293069366|
|   Past State|  72878594|
+-------------+----------+

In questo modo puoi controllare le modifiche ai dati nel tempo.

6. AI strutturata con BigQuery ML

Ora che hai esplorato i dati Iceberg, utilizziamo le funzionalità di AI di BigQuery. Poiché il catalogo Iceberg pubblico è di sola lettura, possiamo utilizzare BigQuery per addestrare un modello nel nostro spazio di lavoro leggendo le tabelle pubbliche.

Crea un set di dati locale

Innanzitutto, crea un set di dati nel tuo progetto per archiviare il modello di AI utilizzando l'interfaccia a riga di comando bq:

bq mk --location=$REGION --project_id=$PROJECT_ID iceberg_ai

Addestra un modello di regressione lineare

Ora addestrerai un modello di regressione lineare utilizzando la tabella Iceberg BigLake pubblica.

Crea un file di query e addestra il modello utilizzando 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

Esegui previsioni utilizzando il modello

Ora che il modello è addestrato, puoi utilizzarlo per prevedere gli importi delle tariffe per i nuovi viaggi utilizzando ML.PREDICT.

Crea un file di query ed esegui la previsione utilizzando 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

Dovresti vedere un output simile al seguente:

+-----------------------+-----------------+---------------+
| predicted_fare_amount | passenger_count | trip_distance |
+-----------------------+-----------------+---------------+
|     14.12252095150709 |               2 |           5.0 |
+-----------------------+-----------------+---------------+

7. AI non strutturata con BigLake

I dati non sono solo righe e colonne. Le data lakehouse unificate gestiscono anche dati non strutturati (immagini, PDF). Utilizziamo tabelle di oggetti e riferimenti a oggetti per eseguire query sui dati non strutturati.

Le tabelle di oggetti sono tabelle esterne di sola lettura in BigQuery che elencano gli oggetti in un percorso Cloud Storage. Ogni riga rappresenta un file, con colonne per i metadati come uri, size e una colonna ref speciale contenente ObjectRef.

I riferimenti a oggetti (ObjectRef) puntano ai dati effettivi di un singolo file. Le funzioni BigQuery ML moderne (come AI.GENERATE o AI.AGG) utilizzano ObjectRef per leggere il contenuto dei file (immagini, audio o testo) per l'analisi senza caricare i byte in una tabella standard.

Crea un set di dati per l'AI non strutturata

Innanzitutto, crea un secondo set di dati nel tuo progetto per archiviare le tabelle di oggetti utilizzando l'interfaccia a riga di comando bq nella regione multipla US:

bq mk --location=US --project_id=$PROJECT_ID iceberg_object_ai

Crea una connessione esterna

Per eseguire query sui dati archiviati in Cloud Storage (sia tabelle di oggetti che dati non strutturati) da BigQuery, devi creare una connessione esterna.

Esegui il comando riportato di seguito in Cloud Shell per creare una connessione alle risorse Cloud:

bq mk --connection --project_id=$PROJECT_ID --location=US --connection_type=CLOUD_RESOURCE my-conn

Trova l'ID del service account creato per la connessione:

CONNECTION_SA=$(bq show --format=json --project_id=$PROJECT_ID --connection $PROJECT_ID.us.my-conn | jq -r '.serviceAccountId // .cloudResource.serviceAccountId')

Concedi al service account i ruoli Utente Vertex AI e Visualizzatore oggetti Storage in modo che possa chiamare i modelli Gemini e leggere i dati 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"

Crea una tabella di oggetti

Utilizzeremo la connessione esterna my-conn creata nella sezione precedente per accedere ai dati non strutturati. Crea un file di query e crea la tabella di oggetti utilizzando 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

Utilizza Gemini sui dati degli oggetti

Ora esegui una query utilizzando Gemini per valutare le immagini senza scaricarle.

Esegui query sulle immagini utilizzando SQL standard tramite 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

Esempio di output:

+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                           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. |
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Esplorazione diretta di ObjectRef: analisi del sentiment

Sebbene le tabelle di oggetti gestiscano automaticamente i riferimenti ai file, puoi interagire direttamente con questi oggetti utilizzando i riferimenti a oggetti di BigQuery per eseguire analisi al volo su singoli file.

Ad esempio, puoi utilizzare un piccolo file di testo archiviato nel tuo bucket GCS (utilizzando la variabile $DEPS_BUCKET creata in precedenza) e analizzarlo utilizzando OBJ.MAKE_REF con bq query.

Innanzitutto, crea un piccolo file di testo e caricalo nel 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

Ora esegui query sul file utilizzando OBJ.MAKE_REF all'interno di 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

Esempio di output:

+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                                 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. Libera spazio

Per evitare addebiti continui sul tuo account Google Cloud, elimina le risorse create durante questo codelab.

Elimina il set di dati e la connessione

Esegui il comando riportato di seguito in Cloud Shell per eliminare i set di dati e la connessione:

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

Elimina i bucket GCS e i file locali

Libera spazio nei bucket GCS e nei file locali:

# 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

Puoi anche eliminare l'intero progetto se l'hai creato solo per questo lab.

9. Complimenti

Complimenti! Hai creato correttamente una data lakehouse unificata utilizzando Apache Iceberg, BigLake e BigQuery AI.

Che cosa hai imparato

  • Come connetterti ed eseguire query sui cataloghi REST di Apache Iceberg pubblici.
  • Utilizzare Time Travel in Iceberg per controllare le versioni del set di dati.
  • Addestrare modelli BigQuery ML su dati strutturati.
  • Connettere dati non strutturati (immagini) utilizzando tabelle di oggetti e ObjectRef.
  • Utilizzare Gemini direttamente in BigQuery SQL per analizzare le immagini.

Documenti di riferimento