OLTP и OLAP: транзакционные и аналитические базы данных
Основы3 минРедакция Innovialabs
Коротко
OLTP-базы обслуживают множество мелких операций приложения: заказы, оплаты, регистрации. OLAP-базы рассчитаны на тяжёлые аналитические запросы по большим объёмам истории. Смешивать эти нагрузки в одной базе — частая причина тормозов в продакшене.
Главное отличие
OLTP (Online Transaction Processing) — это базы, на которых работает само приложение. Пользователь оформил заказ, оплатил, поменял адрес — каждое действие превращается в короткую транзакцию, которая читает или меняет несколько строк. Таких операций много, и каждая должна выполняться за миллисекунды. Типичные примеры: PostgreSQL, MySQL, SQL Server.
OLAP (Online Analytical Processing) — базы для анализа. Запросов к ним меньше, но каждый может перебрать миллионы строк: выручка по месяцам за три года, средний чек по регионам, воронка по каналам. Здесь важна скорость агрегаций, а не отдельных записей. Примеры: ClickHouse, BigQuery, Snowflake.
Сравнение нагрузок
| Параметр | OLTP | OLAP |
|---|---|---|
| Типичная операция | Вставить, обновить или прочитать одну запись | Посчитать сумму, среднее, количество по большому диапазону |
| Объём одного запроса | Несколько строк | Миллионы строк, но несколько столбцов |
| Частота | Очень много коротких запросов | Мало длинных запросов |
| Пользователи | Приложение и его клиенты | Аналитики, BI-инструменты, руководство |
| Приоритет | Целостность, транзакции, низкая задержка | Скорость агрегаций, сжатие, работа с историей |
| Модель данных | Нормализованная, без дублей | Денормализованная, «звезда» и витрины |
Строчное и колоночное хранение
Разница в нагрузке определяет, как данные лежат на диске.
Строчное хранение (OLTP). Все поля одной записи хранятся рядом. Чтобы показать карточку заказа, база читает одно место на диске и сразу получает все поля. Идеально для «найди заказ по ID и обнови статус».
Колоночное хранение (OLAP). Значения каждого столбца хранятся отдельно. Запросу «сумма amount по месяцам» нужны только два столбца из, скажем, тридцати — остальные база вообще не читает. Однотипные значения в столбце к тому же отлично сжимаются.
Обратная сторона: в колоночной базе обновлять отдельные строки дорого, поэтому данные в неё обычно загружают пачками, а не по одной записи.
-- Типичный OLTP-запрос: одна запись по ключу
SELECT status, total FROM orders WHERE id = 48213;
-- Типичный OLAP-запрос: агрегация по всей истории
SELECT date_trunc('month', created_at) AS month, SUM(total)
FROM orders
GROUP BY 1
ORDER BY 1;
Почему отчёты не стоит запускать на рабочей базе
Второй запрос выглядит безобидно, но на большой таблице он:
- Читает всю таблицу и вытесняет из кэша данные, нужные приложению.
- Нагружает процессор и диск, из-за чего обычные запросы пользователей начинают ждать.
- Держит долгий снимок данных, что в PostgreSQL мешает очистке старых версий строк и раздувает таблицы.
- Подталкивает к лишним индексам «под отчёты», которые замедляют каждую запись.
Итог знаком многим: в конце месяца бухгалтерия строит отчёт, а сайт и CRM начинают тормозить.
Что делать вместо этого
- Реплика для чтения. Отдельная копия рабочей базы, на которую направляют отчёты. Самый простой первый шаг.
- Аналитическая база. Регулярная выгрузка данных в ClickHouse, BigQuery или другое колоночное хранилище.
- Витрины. Заранее посчитанные агрегаты, например выручка по дням, чтобы дашборды не пересчитывали всю историю.
- Ограничения. Отдельный пользователь для аналитики с таймаутом на запросы.