← Назад к вопросам

Почему витрины не OBT?

1.6 Junior🔥 151 комментариев
#Архитектура и проектирование#Хранилища данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему витрины не OBT?

OBT (One Big Table) — подход, при котором вся аналитическая информация складируется в одну большую таблицу вместо создания множества нормализованных витрин. Хотя OBT имеет свои преимущества, витрины остаются предпочтительным подходом по целому ряду причин.

Что такое OBT?

OBT — это денормализованная таблица с множеством колонок, где всё в одном месте:

-- OBT подход
CREATE TABLE analytics_big_table AS
SELECT 
  o.order_id,
  o.user_id,
  o.order_date,
  u.user_name,
  u.email,
  u.created_at as user_created_at,
  p.product_id,
  p.product_name,
  p.category,
  p.price,
  pp.payment_method,
  pp.payment_status,
  pp.payment_date,
  s.shipper_name,
  s.tracking_number,
  -- 100+ колонок...
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id
JOIN payments pp ON o.id = pp.order_id
JOIN shipments s ON o.id = s.order_id;

Почему витрины лучше?

1. Управляемость и понятность (Maintainability)

Витрины разбивают данные по смыслу, что делает код понятнее:

-- Витрины подход
CREATE MATERIALIZED VIEW dim_users AS
SELECT id, name, email, created_at FROM users;

CREATE MATERIALIZED VIEW dim_products AS
SELECT id, name, category, price FROM products;

CREATE MATERIALIZED VIEW fact_orders AS
SELECT order_id, user_id, product_id, order_date, amount FROM orders;

CREATE MATERIALIZED VIEW fact_payments AS
SELECT order_id, payment_method, status, payment_date FROM payments;

-- Аналитик понимает, что брать откуда
-- OBT: ищет в 100 колонках

Опытный аналитик сразу знает, что user информация в dim_users, а финансовые данные в fact_payments. С OBT нужно искать в огромной таблице.

2. Производительность запросов (Query Performance)

Великое заблуждение, что OBT всегда быстрее. На самом деле всё наоборот:

-- OBT: 1 таблица с 500 колонками, 100 млн строк
-- Нужно читать все 500 колонок даже если нужны 3
SELECT order_id, user_name, order_date FROM analytics_big_table
WHERE user_id = 123;
-- Сканирует 500 колонок × 100M строк = 50B row reads

-- Витрины: разбиты на меньшие, узкие таблицы
-- Читает только нужные данные
SELECT o.order_id, u.user_name, o.order_date
FROM fact_orders o
JOIN dim_users u ON o.user_id = u.id
WHERE o.user_id = 123;
-- Сканирует 3 колонки × N строк = намного меньше

Базы данных типа Vertica, Snowflake и BigQuery column-oriented — они лучше работают с узкими выборками колонок. OBT со всеми 500 колонками менее эффективен.

3. Масштабируемость и гибкость (Scalability)

Они растут с разными скоростями:

🔴 OBT проблема:
- Нужна новая колонка? Добавляешь в OBT, пересчитываешь ВСЮ таблицу
- Нужно изменить логику одного показателя? Трогаешь большую таблицу
- Каждое изменение = полный пересчёт на 500M строк
- Time to change: 2-4 часа

🟢 Витрины:
- Новая колонка нужна? Создаёшь или обновляешь отдельную витрину
- Изменяешь логику в dim_users? Не трогаешь fact_orders
- Каждое изменение локализовано
- Time to change: 5-10 минут

4. Дублирование и аномалии UPDATE (Update Anomalies)

ОBT создаёт дублирование данных и риск нарушения консистентности:

-- OBT: информация о пользователе дублируется для каждого заказа
SELECT * FROM analytics_big_table LIMIT 3;
-- user_name | user_email | user_created_at
-- John Doe | john@... | 2020-01-01
-- John Doe | john@... | 2020-01-01  ← Дублирование!
-- John Doe | john@... | 2020-01-01

-- Если обновить email пользователя в source system,
-- нужно обновить ВСЕ его записи в OBT (жуткая рассогласованность)

-- Витрины: информация о пользователе в одном месте
SELECT * FROM dim_users WHERE id = 1;
-- id | name | email | created_at
-- 1 | John Doe | john_new@... | 2020-01-01
-- ✅ Одна запись — нет дублирования

5. Тестируемость и валидация (Testability)

Маленькие витрины легче тестировать:

# Тест витрины — простой
def test_dim_users():
    result = query("SELECT COUNT(*) FROM dim_users")
    assert result == expected_user_count
    assert all_emails_valid()
    assert no_duplicates()

# Тест OBT — монструозный
def test_analytics_big_table():
    result = query("SELECT COUNT(*) FROM analytics_big_table")
    # Какой COUNT ожидать? Количество заказов или пользователей?
    # Может быть дублирование из JOIN-ов?
    # Сложно валидировать

6. Доступ и безопасность (Access Control)

Витрины позволяют гранулярный контроль доступа:

ОBT проблема:
- Таблица содержит финансы, HR данные, платёжную информацию
- Либо весь доступ разработчику, либо никакого
- Нельзя дать доступ только к финансовым колонкам

Витрины решение:
- fact_payments — только финансистам (grant select on fact_payments)
- dim_users с зарплатой — только HR (отдельная витрина с ограничениями)
- dim_products — всем аналитикам

7. Версионирование и история (Slowly Changing Dimensions)

При работе с историческими данными витрины более гибкие:

-- Витрина SCD Type 2 (история изменений)
CREATE TABLE dim_users_history AS
SELECT 
  user_id,
  name,
  email,
  valid_from,
  valid_to,
  is_current
FROM users_history;

-- OBT: какую версию user email хранить? Текущую? Историческую?
-- Становится размытым и сложным

8. Современные best practices (Modern Data Stack)

Современный подход — Kimball Dimensional Modeling:

Fact tables (события)
  ├─ order_id
  ├─ user_id (FK -> dim_users)
  ├─ product_id (FK -> dim_products)
  └─ amount

Dimension tables (справочники)
  ├─ dim_users (user_id, name, email, ...)
  ├─ dim_products (product_id, name, category, ...)
  └─ dim_date (date_id, year, month, day, ...)

-- Это витрины, не OBT!

Этот подход стал стандартом в dbt, Looker, Tableau.

9. Скорость расчёта (Calculation Speed)

ОBT часто МЕДЛЕННЕЕ из-за большого размера:

OBT таблица:
- 500 колонок
- 100 млн строк
- На диске: ~400 GB
- Полный пересчёт: 2-4 часа

Витрины (fact + dim):
- Fact таблица: 10 колонок, 100 млн строк = 50 GB
- Dim таблицы: тысячи записей = ~1 GB
- Полный пересчёт: 20-30 минут
- Инкрементальные обновления: 2-5 минут

Когда может быть полезен OBT?

Есть исключения, когда OBT имеет смысл:

1. BI инструменты с плохой оптимизацией JOIN
   (но современные Snowflake/BigQuery это решают)

2. Невероятно частые ad-hoc запросы по разным комбинациям колонок
   (но хорошая индексация витрин это решает)

3. Очень ранний MVP с одной аналитической потребностью
   (но это растёт, и OBT становится проблемой)

Вывод

Витрины — это стандартная архитектура Data Warehouse, потому что:

  • Проще для понимания и поддержки
  • Быстрее на modern column-oriented DB
  • Гибче при изменениях требований
  • Надёжнее в плане консистентности данных
  • Масштабируемее для растущих требований

ОBT — это технический долг, который ломает масштабируемость. Хорошие Data Engineer избегают его, как огня.

Почему витрины не OBT? | PrepBro