1. Introducción
En este codelab, explorarás las capacidades del data lakehouse unificado en Google Cloud. Interactuarás con conjuntos de datos públicos que se publican a través del catálogo REST de Apache Iceberg en BigLake y, luego, aplicarás las capacidades de IA de Google Cloud a los datos estructurados y no estructurados.
Consultarás el conjunto de datos clásico de NYC Taxi con Apache Iceberg, profundizarás en Time Travel para auditar los cambios en los datos y, luego, usarás BigQuery ML y Gemini para ejecutar modelos de IA en tus datos.
Actividades
- Usa Google Cloud Serverless for Apache Spark para consultar los conjuntos de datos públicos de Apache Iceberg alojados en BigLake.
- Consultar datos estructurados en formato Apache Iceberg
- Demostrar la función Time Travel en Apache Iceberg
- Usa BigQuery ML para entrenar un modelo predictivo en datos estructurados.
- Crea una tabla de objetos de BigLake (datos no estructurados) y usa Gemini para analizar imágenes.
Requisitos
- Un navegador web, como Chrome
- Un proyecto de Google Cloud con facturación habilitada.
Costo y duración esperados
- Tiempo para completar: Alrededor de 45 minutos
- Costo estimado: Menos de USD 2.00 Usamos conjuntos de datos públicos y consultas sin servidores para mantener los costos bajos.
2. Configuración y requisitos
En este paso, prepararás tu entorno y habilitarás las APIs necesarias.
Inicie Cloud Shell
Ejecutarás la mayoría de los comandos desde Google Cloud Shell.
- Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud.
- Verifica la autenticación:
gcloud auth list - Confirma tu proyecto:
gcloud config get project - Si el proyecto no está configurado, usa tu ID del proyecto para configurarlo:
gcloud config set project <YOUR_PROJECT_ID>
Habilita las APIs
Ejecuta el siguiente comando para habilitar las APIs requeridas para BigQuery, Cloud Resource Manager y Vertex AI:
gcloud services enable \
bigquery.googleapis.com \
aiplatform.googleapis.com \
cloudresourcemanager.googleapis.com
Configura el entorno y crea un bucket de dependencias
- Configura las variables de entorno en tu terminal:
export PROJECT_ID=$(gcloud config get project) export REGION=us-central1 export DEPS_BUCKET=$PROJECT_ID-deps-bucket - Crea el bucket de Cloud Storage de las dependencias. Los scripts de PySpark se suben aquí en el momento del envío del trabajo:
gcloud storage buckets create gs://$DEPS_BUCKET --location=$REGION
3. Conéctate al catálogo público de Apache Iceberg
En este paso, te conectarás a un catálogo de Apache Iceberg activo y apto para la producción alojado en BigLake de Google Cloud.
Ejecuta Spark SQL con la CLI de Serverless for Apache Spark Batch
Usaremos Google Cloud Serverless for Apache Spark para ejecutar trabajos de PySpark sin necesidad de administrar la infraestructura. Lo configuraremos para que apunte al catálogo público de BigLake REST.
- Define las propiedades del catálogo de REST de BigLake para evitar repetirlas.Esta configuración le indica a Spark lo siguiente:
- Usar las bibliotecas
iceberg-spark-runttimeyiceberg-gcp-bundle - Para configurar un catálogo llamado
my_catalogcon el extremo de REST del catálogo de BigLake. - Para usar Google Cloud Storage (GCS) para leer archivos de datos en lugar del sistema de archivos local predeterminado.
- Establecer este catálogo de
my_catalogcomo el predeterminado para nuestra sesión - Usar credenciales vendidas para mejorar la seguridad y simplificar el acceso a los datos
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" - Usar las bibliotecas
- Crea un archivo de consulta de prueba simple:
cat <<EOF > test.py from pyspark.sql import SparkSession spark = SparkSession.builder.getOrCreate() spark.sql("SHOW TABLES IN public_data").show() EOF - Envía el trabajo por lotes:
Deberías ver un resultado similar al siguiente: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. Consulta datos estructurados de Iceberg
Una vez que te conectes, tendrás acceso completo a los conjuntos de datos a través de SQL. Consultaremos el conjunto de datos de taxis de la ciudad de Nueva York modelado como una tabla de Iceberg.
Ejecuta una consulta de agregación estándar
Crea un archivo llamado 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
Y envíalo con Serverless for 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
Deberías ver un resultado similar a este en la consola:
+---------------+---------+--------+------------+ |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| +---------------+---------+--------+------------+
¿Por qué usar Apache Iceberg aquí?
- Reducción de particiones: La consulta se filtra en
data_file_year = 2021. Iceberg permite que el motor omita por completo el análisis de los datos de otros años. - Agilidad del motor: Puedes ejecutarlo en Spark, Trino o BigQuery sin copiar datos.
5. Time Travel en Apache Iceberg
Una de las funciones más potentes de Iceberg es Time Travel. Te permite consultar los datos tal como existían en una versión o instantánea anterior.
Cómo ver el historial de la tabla
Crea un archivo llamado 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
Y envíalo:
gcloud dataproc batches submit pyspark \
--project=$PROJECT_ID \
--region=$REGION \
--version=2.3 \
--properties="$METASTORE_PROPERTIES" \
--deps-bucket=gs://$DEPS_BUCKET \
history.py
Deberías ver un resultado similar al siguiente en la consola:
+--------------------+-------------------+-------------------+-------------------+ | 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| +--------------------+-------------------+-------------------+-------------------+
Verás filas que representan diferentes IDs de instantáneas y cuándo se confirmaron.
Comparar el recuento de filas actual con el anterior
Crea un archivo llamado 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
Y envíalo:
gcloud dataproc batches submit pyspark \
--project=$PROJECT_ID \
--region=$REGION \
--version=2.3 \
--properties="$METASTORE_PROPERTIES" \
--deps-bucket=gs://$DEPS_BUCKET \
timetravel.py
Deberías ver un resultado similar al siguiente en la consola:
+-------------+----------+ | version| count| +-------------+----------+ |Current State|1293069366| | Past State| 72878594| +-------------+----------+
Esto garantiza que puedas auditar los cambios de datos a lo largo del tiempo.
6. IA estructurada con BigQuery ML
Ahora que exploraste los datos de Iceberg, usemos las capacidades de IA de BigQuery. Como el catálogo público de Iceberg es de solo lectura, podemos usar BigQuery para entrenar un modelo en nuestro espacio de trabajo leyendo desde tablas públicas.
Crea un conjunto de datos local
Primero, crea un conjunto de datos en tu proyecto para almacenar el modelo de IA con la CLI de bq:
bq mk --location=$REGION --project_id=$PROJECT_ID iceberg_ai
Entrena un modelo de regresión lineal
Ahora entrenarás un modelo de regresión lineal con la tabla pública de Iceberg de BigLake.
Crea un archivo de consulta y entrena el modelo con 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
Cómo predecir con el modelo
Ahora que el modelo está entrenado, puedes usarlo para predecir importes de tarifas para viajes nuevos con ML.PREDICT.
Crea un archivo de consulta y ejecuta la predicción con 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
Debería ver un resultado similar al siguiente:
+-----------------------+-----------------+---------------+ | predicted_fare_amount | passenger_count | trip_distance | +-----------------------+-----------------+---------------+ | 14.12252095150709 | 2 | 5.0 | +-----------------------+-----------------+---------------+
7. IA no estructurada con BigLake
Los datos no son solo filas y columnas. Los data lakehouses unificados también controlan datos no estructurados (imágenes, PDFs). Usemos tablas de objetos y referencias de objetos para consultar datos no estructurados.
Las tablas de objetos son tablas externas de solo lectura en BigQuery que enumeran objetos en una ruta de Cloud Storage. Cada fila representa un archivo, con columnas para metadatos como uri, size y una columna especial ref que contiene el ObjectRef.
Referencias de objetos (ObjectRef): Apuntan a los datos reales de un solo archivo. Las funciones modernas de BigQuery ML (como AI.GENERATE o AI.AGG) consumen ObjectRef para leer el contenido de los archivos (imágenes, audio o texto) para el análisis sin cargar los bytes en una tabla estándar.
Crea un conjunto de datos para la IA no estructurada
Primero, crea un segundo conjunto de datos en tu proyecto para almacenar las tablas de objetos con la CLI de bq en la región múltiple US:
bq mk --location=US --project_id=$PROJECT_ID iceberg_object_ai
Crea una conexión externa
Para consultar los datos almacenados en Cloud Storage (tanto las tablas de objetos como los datos no estructurados) desde BigQuery, debes crear una conexión externa.
Ejecuta el siguiente comando en Cloud Shell para crear una conexión de recursos de Cloud:
bq mk --connection --project_id=$PROJECT_ID --location=US --connection_type=CLOUD_RESOURCE my-conn
Busca el ID de la cuenta de servicio que se creó para tu conexión:
CONNECTION_SA=$(bq show --format=json --project_id=$PROJECT_ID --connection $PROJECT_ID.us.my-conn | jq -r '.serviceAccountId // .cloudResource.serviceAccountId')
Otorga a la cuenta de servicio los roles de Usuario de Vertex AI y Visualizador de objetos de Storage para que pueda llamar a los modelos de Gemini y leer datos de 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 tabla de objetos
Usaremos la conexión externa my-conn que creamos en la sección anterior para acceder a los datos no estructurados. Crea un archivo de consulta y la tabla de objetos con 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
Usa Gemini en los datos de objetos
Ahora puedes ejecutar una búsqueda con Gemini para evaluar las imágenes sin descargarlas.
Consulta las imágenes con SQL estándar a través de 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
Resultado de muestra:
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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. |
+----------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Explora ObjectRefs directamente: Análisis de opiniones
Si bien las tablas de objetos administran las referencias de archivos de forma automática, puedes interactuar con estos objetos directamente con las referencias de objetos de BigQuery para ejecutar análisis sobre la marcha en archivos individuales.
Por ejemplo, puedes usar un archivo de texto pequeño almacenado en tu propio bucket de GCS (con la variable $DEPS_BUCKET creada anteriormente) y analizarlo con OBJ.MAKE_REF y bq query.
Primero, crea un archivo de texto pequeño y súbelo a tu 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
Ahora consulta el archivo con OBJ.MAKE_REF dentro de SQL estándar:
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
Resultado de muestra:
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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. Limpia
Para evitar que se apliquen cargos a tu cuenta de Google Cloud, borra los recursos que creaste durante este codelab.
Borra el conjunto de datos y la conexión
Ejecuta el siguiente comando en Cloud Shell para borrar tus conjuntos de datos y la conexión:
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
Borra los buckets de GCS y los archivos locales
Limpia los buckets de GCS y los archivos locales:
# 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
También puedes borrar todo el proyecto si lo creaste solo para este lab.
9. Felicitaciones
¡Felicitaciones! Creaste correctamente un data lakehouse unificado con Apache Iceberg, BigLake y la IA de BigQuery.
Qué aprendiste
- Cómo conectarse a catálogos REST de Apache Iceberg públicos y consultarlos
- Usa Time Travel en Iceberg para auditar versiones de conjuntos de datos.
- Entrenar modelos de BigQuery ML sobre datos estructurados
- Conexión de datos no estructurados (imágenes) con tablas de objetos y ObjectRef
- Usar Gemini directamente en BigQuery SQL para analizar imágenes