Ответ
На моём последнем проекте DWH был построен на Google BigQuery. Это полностью управляемое облачное хранилище данных (Data Warehouse-as-a-Service).
Почему был выбран BigQuery:
- Бессерверная архитектура: Не нужно управлять инфраструктурой, кластерами или тонкой настройкой. Мы могли сосредоточиться на логике данных, а не на администрировании.
- Высокая производительность на больших данных: Использование колоночного хранения (Capacitor) и разделения (sharding) позволяло выполнять аналитические запросы к петабайтам данных за секунды.
- Тесная интеграция с экосистемой GCP: Данные легко загружались из Cloud Storage, обрабатывались в Dataflow (Apache Beam) и визуализировались в Looker Studio. Мы использовали
bqCLI и Python-библиотеку для автоматизации. - Эффективная модель стоимости: Оплата за обработанные терабайты и за хранение, что было выгодно для нашей модели использования с пиковыми нагрузками в конце дня.
Архитектура загрузки данных (ELT):
- Extract: Сырые данные из различных источников (логи приложений, транзакционная БД PostgreSQL, SaaS-сервисы) выгружались в Cloud Storage в формате Parquet.
- Load: С помощью Airflow DAG'ов данные инкрементально загружались в сырой слой (raw layer) BigQuery.
- Transform: Внутри BigQuery выполнялись SQL-трансформации для построения витрин данных (data marts) в консумационном слое. Мы активно использовали представления (views) и материализованные представления (materialized views) для баланса между актуальностью и производительностью.
Пример задачи: Ежедневное обновление витрины для анализа поведения пользователей.
-- В консумационном слое DWH
CREATE OR REPLACE TABLE `project_id.analytics.user_activity_daily`
PARTITION BY date
CLUSTER BY user_segment
AS
SELECT
DATE(timestamp) as date,
user_id,
COUNT(DISTINCT session_id) as sessions,
SUM(revenue) as daily_revenue,
CASE ... END as user_segment
FROM `project_id.raw.events` -- сырой слой
WHERE DATE(timestamp) = CURRENT_DATE() - 1
GROUP BY 1, 2;
Такой подход позволил нам создать масштабируемый и производительный DWH с относительно низкими операционными затратами.
Ответ 18+ 🔞
Ну вот, сидишь такой, думаешь — а не построить ли нам тут хранилище данных, чтобы всё красиво было? И тут на тебе — выбор пал на Google BigQuery. Это, если по-простому, типа как склад данных, но в облаке, и за ним вообще не надо следить, как за злым котом. Полностью управляемая штука, сервис как сервис.
А почему именно его взяли, спросишь? Да похуй, шучу. Вот причины:
- Никаких своих серверов: Вообще, блядь, ноль. Не нужно там кластера собирать, как лего, или настройки какие-то ебаные ковырять. Можно было мозги на логике данных ломать, а не на том, почему этот сервер опять накрылся медным тазом. Удобно, ёпта.
- Скорость на огромных данных просто овердохуища: Там внутри колоночное хранение, умное такое. Можно было ворочать петабайты, а запросы всё равно выполнялись за секунды. Не то что некоторые системы, где на простой отчёт кофе сходить можно.
- Всё в одной песочнице GCP: Данные из Cloud Storage залетали, обрабатывались в Dataflow, а потом в Looker Studio красота наводилась. Мы ещё скриптами на Python и
bqCLI всё автоматизировали — красота, а не жизнь. - Платишь только за то, что съел: Модель стоимости — за обработанные терабайты и за место на диске. Для нас, где в конце дня всё грузилось, а ночью тишина, — вышло очень даже выгодно. Не то что круглосуточно за выделенные мощности платить.
Как мы данные таскали (по принципу ELT):
- Вытащить (Extract): Всё сырьё — логи, транзакции из PostgreSQL, данные из разных сервисов — сливали в Cloud Storage, в формат Parquet.
- Загрузить (Load): Потом, через Airflow DAG'ы, это добро инкрементально пихали в сырой слой BigQuery. Всё как по маслу.
- Преобразовать (Transform): А вот тут уже внутри самого BigQuery начиналась магия на SQL. Делали витрины данных для аналитиков. Активно юзали вьюхи и материализованные вьюхи — чтобы и быстро было, и данные свежие. Баланс, блядь, тонкий.
Вот тебе живой пример задачи: Ежедневно надо было витрину по активности пользователей обновлять.
-- В консумационном слое DWH
CREATE OR REPLACE TABLE `project_id.analytics.user_activity_daily`
PARTITION BY date
CLUSTER BY user_segment
AS
SELECT
DATE(timestamp) as date,
user_id,
COUNT(DISTINCT session_id) as sessions,
SUM(revenue) as daily_revenue,
CASE ... END as user_segment
FROM `project_id.raw.events` -- сырой слой
WHERE DATE(timestamp) = CURRENT_DATE() - 1
GROUP BY 1, 2;
В общем, такой подход позволил нам развернуть масштабируемое хранилище, которое не падало под нагрузкой и не требовало, чтобы его постоянно гладили по голове. Операционных затрат — минимум, а результата — на гора.