Создание единого хранилища данных для ИИ с использованием Apache Iceberg и BigLake.

1. Введение

В этом практическом занятии вы изучите возможности унифицированного хранилища данных Unified Data Lakehouse в Google Cloud. Вы будете взаимодействовать с общедоступными наборами данных, предоставляемыми через REST-каталог Apache Iceberg на BigLake , а затем применять возможности искусственного интеллекта Google Cloud как к структурированным, так и к неструктурированным данным.

Вы будете выполнять запросы к классическому набору данных о нью-йоркских такси с помощью Apache Iceberg, углубляться в изучение Time Travel для проверки изменений данных, а затем использовать BigQuery ML и Gemini для запуска моделей искусственного интеллекта на ваших данных.

Что вы будете делать

  • Используйте Google Cloud Serverless для Apache Spark, чтобы выполнять запросы к общедоступным наборам данных Apache Iceberg, размещенным на BigLake.
  • Выполнение запросов к структурированным данным в формате Apache Iceberg.
  • Продемонстрируйте путешествие во времени в фильме «Апачи Айсберг».
  • Используйте BigQuery ML для обучения прогностической модели на структурированных данных.
  • Создайте объектную таблицу BigLake (неструктурированные данные) и используйте Gemini для анализа изображений.

Что вам понадобится

  • Веб-браузер, например Chrome .
  • Проект Google Cloud с включенной функцией выставления счетов.

Ожидаемая стоимость и продолжительность

  • Время выполнения : ~45 минут.
  • Ориентировочная стоимость : < 2,00 долл. США. Для снижения затрат мы используем общедоступные наборы данных и бессерверные запросы.

2. Настройка и требования

На этом этапе вы подготовите свою среду и включите необходимые API.

Запустить Cloud Shell

Большинство команд вы будете выполнять из Google Cloud Shell .

  1. В верхней части консоли Google Cloud нажмите кнопку «Активировать Cloud Shell» .
  2. Проверка подлинности:
    gcloud auth list
    
  3. Подтвердите свой проект:
    gcloud config get project
    
  4. Если проект не задан, задайте его, используя идентификатор вашего проекта:
    gcloud config set project <YOUR_PROJECT_ID>
    

Включить API

Выполните следующую команду, чтобы включить необходимые API для BigQuery , Cloud Resource Manager и Vertex AI :

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

Настройка среды и создание корзины зависимостей

  1. Настройте переменные окружения в терминале:
    export PROJECT_ID=$(gcloud config get project)
    export REGION=us-central1
    export DEPS_BUCKET=$PROJECT_ID-deps-bucket
    
  2. Создайте корзину Cloud Storage для зависимостей. Скрипты PySpark загружаются сюда во время отправки задания:
    gcloud storage buckets create gs://$DEPS_BUCKET --location=$REGION
    

3. Подключитесь к общедоступному каталогу Apache Iceberg.

На этом этапе вы подключитесь к работающему, пригодному для производственной эксплуатации каталогу Apache Iceberg, размещенному на платформе Google Cloud BigLake.

Запуск Spark SQL с использованием бессерверных технологий для Apache Spark Batch CLI

Мы будем использовать Google Cloud Serverless для Apache Spark, чтобы запускать задания PySpark без необходимости управления инфраструктурой. Мы настроим его так, чтобы он указывал на общедоступный REST-каталог BigLake.

  1. Определите свойства каталога REST BigLake, чтобы избежать их повторения. Эта конфигурация сообщает Spark:
    • Для использования библиотек iceberg-spark-runttime и iceberg-gcp-bundle .
    • Чтобы настроить каталог с именем my_catalog , используя конечную точку REST Catalog BigLake .
    • Для чтения файлов данных вместо стандартной локальной файловой системы используйте Google Cloud Storage (GCS) .
    • Чтобы установить каталог my_catalog в качестве каталога по умолчанию для нашей сессии.
    • Использование учетных данных, предоставленных поставщиками, для повышения безопасности и упрощения доступа к данным.
    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. Создайте простой тестовый файл запроса:
    cat <<EOF > test.py
    from pyspark.sql import SparkSession
    
    spark = SparkSession.builder.getOrCreate()
    
    spark.sql("SHOW TABLES IN public_data").show()
    EOF
    
  3. Отправьте пакетное задание:
    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. Запрос структурированных данных айсберга.

После подключения вы получите полный доступ к наборам данных через SQL. Мы будем выполнять запросы к набору данных о нью-йоркских такси, представленному в виде таблицы типа «айсберг».

Выполните стандартный агрегационный запрос

Создайте файл с именем 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

И отправьте его, используя Serverless для 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

В консоли вы должны увидеть примерно такой вывод:

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

Почему здесь используется Apache Iceberg?

  • Фильтрация по разделам : запрос фильтрует данные по data_file_year = 2021 Iceberg позволяет движку полностью пропускать сканирование данных за другие годы.
  • Гибкость движка : Вы можете запускать это в Spark, Trino или BigQuery без копирования данных!

5. Путешествие во времени в «Апачи Айсберге»

Одна из самых мощных функций Iceberg — это «Путешествие во времени» . Она позволяет запрашивать данные в том виде, в котором они существовали в предыдущей версии или снимке.

Просмотреть историю таблицы

Создайте файл с именем 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

И отправьте его:

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

В консоли вы должны увидеть вывод, похожий на следующий:

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

Вы увидите строки, представляющие различные идентификаторы снимков и время их фиксации.

Сравните текущее и предыдущее количество строк.

Создайте файл с именем 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

И отправьте его:

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

В консоли вы должны увидеть вывод, похожий на следующий:

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

Это позволит вам отслеживать изменения данных с течением времени.

6. Структурированный ИИ с использованием машинного обучения BigQuery

Теперь, когда вы изучили данные Iceberg, давайте воспользуемся возможностями BigQuery AI! Поскольку общедоступный каталог Iceberg доступен только для чтения, мы можем использовать BigQuery для обучения модели в нашем рабочем пространстве, считывая данные из общедоступных таблиц.

Создайте локальный набор данных

Сначала создайте в своем проекте набор данных для хранения модели ИИ, используя интерфейс командной строки bq :

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

Обучение модели линейной регрессии

Теперь вы обучите модель линейной регрессии, используя общедоступную таблицу BigLake Iceberg.

Создайте файл запросов и обучите модель, используя 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

Сделайте прогноз, используя модель.

Теперь, когда модель обучена, вы можете использовать ее для прогнозирования стоимости проезда в новых поездках с помощью ML.PREDICT .

Создайте файл запроса и выполните прогнозирование с помощью 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

В результате вы должны увидеть примерно следующий вывод:

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

7. Неструктурированный ИИ с использованием BigLake

Данные — это не только строки и столбцы. Unified Data Lakehouses также обрабатывает неструктурированные данные (изображения, PDF-файлы). Давайте воспользуемся объектными таблицами и объектными ссылками для запроса неструктурированных данных.

Таблицы объектов — это внешние таблицы только для чтения в BigQuery, содержащие список объектов, находящихся в пути Cloud Storage. Каждая строка представляет собой файл, с столбцами для метаданных, таких как uri , size , и специальным столбцом ref содержащим ObjectRef .

Объектные ссылки ( ObjectRef ) указывают на фактические данные отдельного файла. Современные функции машинного обучения BigQuery (например, AI.GENERATE или AI.AGG ) используют ObjectRef для чтения содержимого файла (изображений, аудио или текста) для анализа без загрузки байтов в стандартную таблицу.

Создайте набор данных для неструктурированного ИИ.

Во-первых, создайте в своем проекте второй набор данных для хранения таблиц объектов, используя интерфейс командной строки bq в многорегиональной версии US :

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

Создать внешнее подключение

Для запроса данных, хранящихся в Cloud Storage (как объектных таблиц, так и неструктурированных данных), из BigQuery необходимо создать внешнее подключение.

Для создания подключения к облачному ресурсу выполните следующие действия в Cloud Shell:

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

Найдите идентификатор учетной записи службы, созданной для вашего подключения:

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

Предоставьте учетной записи службы роли пользователя Vertex AI и средства просмотра объектов хранилища , чтобы она могла вызывать модели Gemini и считывать данные 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"

Создайте таблицу объектов.

Для доступа к неструктурированным данным мы будем использовать внешнее соединение my-conn созданное в предыдущем разделе. Создайте файл запроса и таблицу объектов с помощью 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

Используйте Gemini для обработки объектных данных.

Теперь выполните запрос с помощью Gemini, чтобы оценить изображения, не загружая их!

Запрос изображений с использованием стандартного SQL- 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

Пример выходных данных:

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

Непосредственное изучение ObjectRefs: анализ настроений

В то время как объектные таблицы автоматически управляют ссылками на файлы, вы можете взаимодействовать с этими объектами напрямую, используя ссылки на объекты BigQuery, чтобы выполнять анализ отдельных файлов в режиме реального времени.

Например, вы можете использовать небольшой текстовый файл, хранящийся в вашем собственном хранилище GCS (используя созданную ранее переменную $DEPS_BUCKET ), и проанализировать его с помощью OBJ.MAKE_REF с bq query .

Сначала создайте небольшой текстовый файл и загрузите его в свой бакет:

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

Теперь выполните запрос к файлу, используя OBJ.MAKE_REF в стандартном SQL-запросе:

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

Пример выходных данных:

+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                                                 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. Уборка

Чтобы избежать дальнейших списаний средств с вашего аккаунта Google Cloud, удалите ресурсы, созданные в ходе этого практического занятия.

Удалить набор данных и соединение

Для удаления наборов данных и подключения выполните следующие действия в Cloud Shell:

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

Удалите корзины GCS и локальные файлы.

Очистите хранилища GCS и локальные файлы:

# 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

Вы также можете удалить весь проект, если создавали его только для этой лабораторной работы.

9. Поздравляем!

Поздравляем! Вы успешно создали единое хранилище данных (Unified Data Lakehouse) с использованием Apache Iceberg, BigLake и BigQuery AI!

Что вы узнали

  • Как подключиться к общедоступным REST-каталогам Apache Iceberg и выполнять запросы к ним.
  • Использование функции "Путешествие во времени" в Iceberg для проверки версий набора данных.
  • Обучение моделей машинного обучения BigQuery на структурированных данных.
  • Соединение неструктурированных данных (изображений) с помощью объектных таблиц и объектных ссылок.
  • Использование Gemini непосредственно в BigQuery SQL для анализа изображений.

Справочная документация