Привет, ХАБР! Я Владимир Хаймин, эксперт по системам управления базами данных PostgreSQL в ВТБ. Когда вы знакомитесь с документацией по какой-то системе в части базы данных, то обычно характер нагрузки определяется исходно в архитектуре проекта. Но если система определена архитектором как OLTP, но в действительности может вести себя в некоторые периоды времени как OLAP. Нормально ли такое поведение, и каким образом мы можем определить, что она ведет себя как-то иначе? Как определить фактический профиль нагрузки OLAP или OLTP и выразить это через метрики, пригодные для событийного и графического мониторинга?
Эта статья является скорее исследовательской в области Data Science в прикладном контексте PostgreSQL. Data Science – это не только задачи ИИ: (ML, LLM,..), но прежде всего математика. Мы используем регрессивные методы для получения некоторых нужных нам параметров исходя из табличных рекомендованных данных. Также мы делаем упор на исследование состояния БД на основе статистики динамики ожиданий. Задача, несмотря на ее простой смысл, в решении оказалась не такой простой, и мы в итоге работали над ней довольно долго, хоть и в фоновом режиме. Также обратились к студенческому сообществу и провели по этой теме Хакатон ВТБ х Башня, прошедший в МГТУ им. Баумана 27 ноября 2025 года. В нем приняли участие студенты и выпускники НИУ ВШЭ, СПбГУ, ВКА им. А.Ф. Можайского, РАНХИГС, Московского Политехнического университета, НИТУ МИСИС, а также уже действующие архитекторы и администраторы БД. У команд было всего три дня на решение задачи, и хотя полностью её не удалось выполнить никому, совокупный результат всех участников позволил сформировать корректное решение. Результат именно этих работ я и изложил в статье и обязательно буду упоминать команды и авторов интересных идей, о которых пойдет речь.
Для чего это нужно? Прежде всего для диагностики наличия проблем в системе. Если выяснилось, что БД ведет себя совсем не так, как определено архитектором - само по себе является проблемой. Каждый из профилей имеет свои рекомендации по настройке параметров БД, операционной системы, режиму обслуживания и даже расписанию бекапов. И если профиль изменяется, то нужно менять и эти параметры или предпринимать что то еще. Возможно система была изначально задумана именно с таким смешанным поведением, и архитектор сообщит о допустимости таких отклонений. Но если это незапланированное отклонение, и вы имеете профиль нагрузки отличный от того что должно быть – это может означать, что где-то мы просчитались. Возможно, нагрузка слишком высока, у нас недостаточно ресурсов для работы БД, нет нужных индексов или потребуются архитектурные изменения (нормализация/денормализация, секционирование и т.д.).
Также я хотел бы показать, в чем особенности других профилей нагрузки. Особенно остановиться на Archive Database, когда База Данных переведена в Архив, но выясняется, что в действительности ведет себя как скрытый продуктив и активно используется. Какие риски могут быть при продуктивном использовании Архивных БД?
Основные профили нагрузки OLAP и OLTP.
С точки зрения администратора базы данных, ключевое различие между OLAP (Online Analytical Processing) и OLTP (Online Transaction Processing) заключается в характере потока запросов и как следствие в методе настройки, который вы применяете непосредственно к БД:
· Если вам необходимо обработать большие объемы данных для получения результатов запроса или какого-то сложного аналитического отчета, вы имеете OLAP профиль. Этому профилю характерен относительно медленный доступ к достаточно крупному объему данных. Допустимы тяжелые последовательные чтения.
· И наоборот, если удается использовать очень небольшое количество данных, выполняемых простыми короткими запросами для получения возвращаемых значений, вы имеете OLTP профиль. Здесь доступ даже к большим таблицам должен быть быстрым, как правило индексным.
Смешанные профили нагрузки.
Нагрузка может иметь смешанный характер. Например, в основном ее профиль определяется как OLTP, состоит из достаточно большого числа коротких запросов, требующих обработки небольших объёмов данных. Но иногда в этой же системе требуется строить какие-то аналитические запросы или производить объемные загрузки или модификации данных. В этом случае профиль ведет себя как OLAP. Такие профили также имеют свое название, в частности, наиболее известен тип HTAP (Hybrid Transactional/Analitics Processing) как профиль, характеризующийся одновременно OLAP и OLTP характером нагрузки.
Но существуют и другие типы нагрузки, которые могут в той или оной степени иметь свойства OLAP, OLTP, HTAP, но их часто выделяют как отдельные типы, если требуются особенные свойства этих БД. На рисунке представлены все профили, которые рассматривали в своих работах участники Хакатон ВТБ х Башня. Особенное внимание этому уделили команды «404 Logic not found», «Flashing lights» НИУ ВШЭ и «HTTP18».
Так или иначе, другие профили ведут себя как вариации этих основных профилей – OLAP / OLTP / HTAP (который в свою очередь является гибридом OLAP/OLTP). Но со своими особенностями.

Внимание, вопрос. Когда вы на БД запускаете VACUUM FULL, как думаете, какой это профиль нагрузки? Оказывается, и для этого есть название. Профиль называется Data Maintenance (!) Как видно из рисунка, он является вариацией профиля OLAP по характеру нагрузки.
Комбинированные метрики для оценки состояния БД
На базовом уровне для определения профиля нагрузки важно отделить длинные и короткие запросы в соотношении с их частотой, ��о требуется понять, каким образом их научиться разделять.
Для понимания этого нужно в целом увидеть, как База данных «ощущает» такие профили.
Вопрос: Что ожидает программист, разработчик от БД, когда написал совершенно новый запрос? Как быстро, по его мнению, он должен выполниться? И как ведет себя система, если таких запросов много, и они конкурируют?
Ответ: Предполагаю, что разработчик ожидает, чтобы результат запроса БД ему выдала сразу, почти мгновенно. Идеальная БД всегда должна давать результат мгновенно. Если этого не происходит, то БД столкнулась с какими-то трудностями на пути выполнения запроса. Что это может быть?
· Для выполнения запроса требуется прочитать слишком большие объёмы данных. Хорошо если они уместились в shared_buffers, но, если нет – потребуется их читать с диска, а операции IO более чем на порядок медленнее чтений из оперативной памяти.
· Запрос может быть заблокирован, ожидает другую сессию, которая бы освободила нужные этому запросу данные. Хотя эта ситуация может быть не связана непосредственно с нагрузкой на чтение большого числа данных, слишком высокая конкуренция в итоге приводит к значительному замедлению выполнения запросов.
· Поток запросов слишком высок для данной системы с имеющимися техническими возможностями. То есть, например, если вы посылаете на систему поток 100, 1000 TPS, то запросы выполняются достаточно быстро. Например, 1500 TPS вызывает существенную деградацию, а поток 2000 TPS может вовсе привести к аварии БД.
В PostgreSQL для мониторинга всех актуальных на текущий момент состояний, которые испытывает запрос (или, точнее, сессия) удобно использовать представление pg_stat_activity. Оно содержит три ключевых поля, которые позволяют однозначно определить состояние каждой сессии:
state – общее текущее состояние этого серверного процесса. Наиболее важные значения (подробнее см. в документации):
active: серверный процесс выполняет запрос.
idle: серверный процесс ожидает новой команды от клиента.
idle in transaction: серверный процесс находится внутри транзакции, но в настоящее время не выполняет какой-либо запрос.
wait_event – имя ожидаемого события, если обслуживающий процесс находится в состоянии ожидания, а в противном случае — NULL (подробнее см. в документации)
wait_event_type – тип события, которого ждёт обслуживающий процесс, если это ожидание имеет место; в противном случае — NULL (подробнее см. в документации)
Но если скомбинировать через конкатенацию все три параметра, мы можем получить очень детальную информацию о состоянии Базы данных в целом.
Ниже несколько примеров из реальной системы в такой комбинации state + wait_event + wait_event_type



Такой график в динамике может передать основные события на Базе данных в разные периоды времени, по которым можно дать однозначный ответ о состоянии БД.
Как пример – ниже запрос, которым можно получить такую динамику. Это можно делать и через zabbix, модифицировав запрос извлечения данных «ощущения» БД.
select pa.state ' ' coalesce(wait_event, ' ')|| ' ' || coalesce(wait_event_type, ' ') ash_state, count(*) cnt from pg_stat_activity pa where pa.state <> 'idle' group by state, wait_event, wait_event_type order by state , wait_event, wait_event_type;
Состояния Базы данных:
Относительно профиля нагрузки, если состояние большинства активных сессий находятся в состоянии sate = active со значением NULL по полям wait_event и wait_event_type – это означает, что БД выполняет запросы и не чувствует никаких затруднений. В таблице некоторые примеры комбинации трех полей, характеризующей «ощущения БД» в таблице:
state | wait_event | wait_event_type | Комментарий |
active |
|
| Сессия активна и не ждет какого-либо события. Она на CPU и выполняет полезную работу. Если таких сессий много и запросы выполняются долго, это говорит о высокой нагрузке на CPU или неэффективных запросах. Если время выполнения приемлемо, то это нормальный OLTP профиль. |
active | relation | Lock | Сессия активна, но заблокирована другой сессией, пытаясь получить доступ к таблице. Конфликт блокировок. Необходимо найти блокирующую сессию (часто это idle in transaction или длительный active) с помощью pg_locks и завершить ее или оптимизировать код приложения. |
active | DataFileRead | IO | Система читает данные с диска и есть ожидания на IO. Она активна и ждет, пока данные будут считаны с диска в буферный кэш. Проблема ввода-вывода. Низкая эффективность кэширования (низкий cache hit ratio) или медленная дисковая подсистема. Это нормально для OLAP, но может быть ненормально для OLTP. |
active | buffer_mapping | LWLock | Сессия активна и ждет доступа к внутренней структуре данных (облегченной блокировке). Часто возникает при конкурентной работе с буферами. Конкуренция за внутренние ресурсы. Может указывать на необходимость настройки параметров памяти (например, shared_buffers) или оптимизации запросов. |
idle in transaction | ClientRead | Client | Сессия удерживается ППО в открытой транзакции и ожидает действий со стороны ППО. Сессия открыла транзакцию (BEGIN;), но пока ничего не делает и ждет следующей команды от клиента. Самая опасная ситуация для блокировок, т.к. она не зависит от БД, а зависит от проблем внешних на ППО. Эта сессия удерживает все locks, полученные в транзакции. Это частая причина простоев, которую необходимо выявлять и устранять на уровне приложения. |
active | SyncRep | IPC | Активная сессия работает с синхронными репликами и ожидает применения логов на репликах. Но также есть конкуренция по IPC |
Для более точного понимания комбинаций state + wait_event + wait_event_type, значения параметров ожиданий, всегда обращайтесь в документацию PostgreSQL. С накоплением опыта любая комбинация этих полей вам может сразу рассказать о состоянии Базы данных, и тех проблемах, которые она испытывает. Например, здесь:
https://postgrespro.ru/docs/postgresql/current/monitoring-stats#MONITORING-PG-STAT-ACTIVITY-VIEW
DB Time (по ASH, или COMMITED).
Многим из Oracle известно понятие DB Time. Это суммарное время, которое сессии (клиенты) потратили на время полезной работы или находились в состоянии ожидания ресурсов (диск, память, блокировки). То есть находятся в состоянии no idle в какое-то определенное время. Эта метрика фактически суммирует все сессии, находящиеся в данном состоянии в какой-то конкретный момент времени.
В PostgreSQL удобно для измерения DB Time в контексте Orcale использовать представление pg_stat_activity. В какой-то конкретный момент времени считаем, что отдельная no idle сессия выполняет запрос или ожидает что-то. Тогда суммарное время всех запросов, которые что-то выполняют, но находятся в таком состоянии:
select sum(now()-pa.query_start) from pg_stat_activity pa where pa.backend_type = 'client backend' and pa.state <> 'idle';
Или если у вас есть снимки pg_stat_activity:
select pa.snap_ts, 'DB_TIME (ASH)' lvl, extract (epoch from sum(pa.snap_ts - pa.query_start)) db_tme from "rds_pg_stats".snap_pg_stat_activity pa where pa.snap_ts < now() and pa.snap_ts > now() - interval '540 min' and pa.state <> 'idle' and pa.backend_type = 'client backend' group by snap_ts order by snap_ts;
Пример динамики DB Time (по pg_stat_activity) или DB Time (ASH) в одной из реальных систем:

Ограничение такого подхода состоит в том, что мы видим таким образом только запросы, когда непосредственно снимаем метрику, но не знаем, что было между этими снимками. То есть DB Time имеет «слепые зоны». Этот метод видит то, что происходит на мгновенном временном срезе, но не видит то, что происходило между этими срезами. Это удобно для измерения достаточно длинных запросов, сопоставимых с интервалом сбора метрики, но совершенно не подходит для большого числа коротких запросов.
С другой стороны, в PostgreSQL есть расширение pg_stat_statement. Если нет вытеснения, то это расширение агрегируют абсолютно все выполненные запросы в интервале. В этом случае мы получим информацию обо всех завершенных запросах в нужном нам интервале времени. Это время может быть коротким, если сессии не испытывали затруднений, и увеличиваться в случае ожиданий и блокировок. То есть это как раз то, что нам нужно(!)
Ключевой параметр здесь можно принять как изменение столбца total_exec_time. Для демонстрации можно использовать такой запрос (это не рабочий запрос, он нужен просто для объяснения смысла, рабочий гораздо длиннее):
select ssp1.snap_id, (sum(ssp1.total_exec_time) - sum(ssp2.total_exec_time))/1000 dbtme_com from snap_pg_stat_statements ssp1, snap_pg_stat_statements ssp2 where ssp1.snap_ts < now() and ssp1.snap_ts > now() - interval '240 min' and ssp2.snap_id = ssp1.snap_id - 1 group by ssp1.snap_id;
Более наглядно увидеть разницу между DB Time (ASH) и DB Time (committed) можно на таком графике:

Верхний рисунок представляет классический OLTP профиль. Мы видим много коротких запросов, некоторая часть которых видна через механизм DB Time (ASH) – оранжевые полосы, но все же доля запросов, собранных через pg_stat_statements DB Time (committed) – синие полосы выше. На нижнем рисунке: если появляются длинные запросы, то увеличивается доля DB Time (ASH) профиль смещается в сторону OLAP.
Как понятно из рисунков – это позволяет иметь представление о профиле нагрузки OLAP/OLTP, поэтому для оценки профиля нагрузки мы должны видеть эти обе метрики вместе.
Как выглядят DB Time ASH и DB Time Committed совместно в динамике вы можете увидеть ниже. Здесь представлен пример для одной из реальных систем с абсолютными значениями времени этих метрик:

Как это интерпретировать?
По графику мы видим, что в основном преобладает DB Time Committed, много коротких запросов, но периодически появляются длинные запросы.
В ожиданиях тот же период времени выглядит так:

Как видим, есть корреляция между всплесками DB Time ASH, но их природа разная. Первый всплеск обусловлен блокировками (active + Transactionid + Lock и active + Tuple + Lock), второй – удержаниями открытых сессий со стороны ППО, которые вызывали и блокировки, (idle in transaction + ClientRead + Client).
Формула профиля нагрузки. Соотношение DB TIME (ASH) и DB TIME (COMMITTED).
Для определения профиля важнее знать не столько абсолютные значения DB Time, сколько их отношение.
То есть упрощенно, если Profile ratio близок к 1000 = это OLAP профиль, если близок к 0 = это OLTP профиль. Если по середине – то профиль смешанного типа, например, HTAP. Коэффициент 1000 выбран для удобства, чтобы параметры были целыми в диапазоне 0–1000, а не вещественной области 0–1.
Однако есть вероятность, что при очень низкой нагрузке DBTime ash + DBTime committed = 0 и вы получите деление на 0. Однако в реальности на БД все равно идут какие-то запросы, например, мониторинга, и вероятность этого очень низкая.
Какой интервал сбора метрик наиболее оптимален?
Какие границы выбрать, какой интервал сбора метрик оптимален? Экспериментально мы получили такие данные для Profile ratio для разных интервалов сбора метрики от трех независимых исследователей, причем два исследователя сошлись во мнении для интервала ∆t = 1 мин. Я благодарю участников Хакатона ВТБ х Башня команду «MozhaHackers» (СПбГУ, ВКА) и «Команду 3» за предоставленные данные:
Профиль нагрузки | Profile ratio (∆t = 1 min) | Profile ratio (∆t = 5 min) |
OLTP | 0-500 | 0-300 |
HTAP | 500-900 | 300-700 |
OLAP | 900-1000 | 700-1000 |
В таблице видно, что для ∆t = 1 min параметры смещены ближе к 1000, а для ∆t = 5 min находятся ближе в середине значений. То есть существуют какие-то оптимальные значения времени выборки ∆t.
Выведем эмпирические формулы по экспоненциальной регрессии для точек из таблицы.
Для ∆t = 1 min:
Для ∆t = 5 min:
Здесь ∆t – интервал сбора метрики в минутах
Profile ratio OLAP- граница области для профиля OLAP.
Profile ratio HTAP- граница области для профиля HTAP.
На графике:

Как видно из графика, при слишком больших значениях ∆t границы профилей OLAP и HTAP стремятся к нулю, что приводит к накоплению ошибки и, при дальнейшем росте параметра, к снижению различимости между ними. То же при слишком малых значениях ∆t – они становятся малоотличимы от верхней границы значений профиля 1000. То есть сбор метрик DB Time как по ASH так и Committed например при ∆t = 1 сек слишком мало, так как Profile ratio для OLAP и HTAP близок к 1000, и речь идет о ∆t выраженного в минутах. И хотелось бы, чтобы обе границы находились симметрично относительно середины 500 единиц Profile ratio.
Несмотря на то что графики не совпадают, они дают нам представление о порядке величин для интервала сбора метрик ∆t.
Наиболее оптимальное значение ∆t находится в интервале от 2 до 7 мин. Но очень удобно из-за кратности 1 часу использовать ∆t = 5 мин. Именно такое значение мы и рекомендуем применять на практике.
Как это выглядит на практике.
Пример классической OLAP нагрузки реальной системы:

Пример OLTP системы, которая проявляет себя и как гибридная HTAP, но все же не проявляет себя как чистая OLAP:

Что делать, если фактический профиль нагрузки не соответствует тому, как это определил архитектор?
Несоответствие профиля говорит о том, что нагрузка не соответствует выделенным ресурсам, либо сама архитектура требует оптимизации или переработки. То есть произошел случай, когда вы на «Запорожце» пытаетесь перевезти то, что можно перевозить только на «Камазе». Либо наоборот, когда тяжелую технику вроде трактора пытаетесь использовать как велосипед. Это весьма неприятные ситуации) Ниже опишу самый базовый подход, т.к. вопросы оптимизации ресурсов, запросов и архитектуры не входят рамки этой статьи. В данном случае сам факт изменения профиля – это как триггер, который нам говорит о том, что с БД что-то не так, и нужно предпринимать какие-то дополнительные более глубокие методы исследования.
Итак, у вас изменился профиль нагрузки, вы локализовали проблему. Что делать?
«Простой», не всегда эффективный и дорогой метод – увеличение ресурсов.
Если вы видите большую часть сессий в состоянии active DataFileRead IO для профиля OLAP – это говорит о том, что не все блоки находятся в ОЗУ и значительную часть приходится читать с диска. В данном случае может помочь увеличение ОЗУ и параллельно shared_buffers. Либо увеличить IOPS для системы хранения, это более актуально для OLAP.
Значительная доля active … IPC или active … LW Lock (в сочетании с волооким LA и Context switches) говорит о высокой нагрузке и конкуренции на уровне ЦПУ, вероятно нужно увеличить число ядер процессора.
Оптимизация запросов, архитектуры
При высокой доле запросов, читающих из Shared Buffers или Shared Blocks Read часто очень эффективны индексы. Хотя из-за селективности это не всегда возможно.
Переписать запрос на более удобный с т.з. оптимизатора PostgreSQL.
Можно прибегнуть к секционированию больших таблиц, если есть какой-то возможный с точки зрения логики ППО ключ секционирования.
Иногда помогают методы нормализации или денормализации для оптимизации размера данных.
Важно понимать, что изменение профиля – это не просто информация. Это повод для действий либо по переконфигурации БД, либо по оптимизации запросов или структуры БД.
Прежде чем свести все интересные для нас профили в единую систему, отдельно хотелось остановиться на особенностях Archive (Архивного профиля). Это не менее важный профиль, чем основные, и хотелось бы описать его более детально.
ARCHIVE DATABASE (Архивный профиль)
Архивная база данных (Archival Database, Historical Database, Read-Only Archive) – это специализированное хранилище данных, основная цель которого – долгосрочное сохранение исторических, неизменяемых или редко изменяемых данных для целей аналитической обработки, аудита, соответствия регуляторным требованиям и редких оперативных запросов.
Ключевой аспект: Архивная БД – это не просто «старая копия продуктивной базы», а специализированная система, спроектированная и настроенная под конкретный, ограниченный профиль доступа, где целевой аспект хранения данных преобладает над производительностью операций чтения и записи. Если ваша «архивная» база не соответствует этим критериям – вы имеете скрытый продуктив, что ведет к неправильному распределению ресурсов и рискам.
В академической литературе и индустрии Баз данных используются термины:
Write-Once Read-Many (WORM) – подчеркивает режим доступа.
Cold Storage / Cold Data Repository – акцент на «температуре» данных.
Historical Data Warehouse (в узком смысле) – акцент на аналитике.
Compliance Archive – акцент на нормативных требованиях.
Критерии архивной БД (идеальный профиль)
1. Режим доступа к данным (главный критерий)
Соотношение операций: 99%+ чтения, <1% записи.
Тип записи: исключительно периодические (раз в сутки/месяц) добавления новых порций данных, либо административные исправления.
Характер чтения: преимущественно аналитические запросы (OLAP) — full scans, агрегации, соединения больших объемов.
2. Требования к производительности
Высокая пропускная способность на последовательное чтение > низкая задержка случайного доступа.
Допустимы длительные запросы: от секунд до часов (в отличие от OLTP, где SLA обычно <1 сек).
Низкий приоритет выполнения: запросы могут быть отложены или выполняться в периоды низкой нагрузки.
3. Модель данных и схема
Данные неизменяемы (immutable) после архивации.
Денормализация допустима и часто полезна для ускорения аналитических запросов.
Временные ряды и версионность – базовые паттерны.
Минимум индексов (только под ключевые запросы), так как поддержка индексов при записи дорога.
4. Требования к доступности и согласованности
Более высокие RPO/RTO допустимы: восстановление может занимать часы.
Слабая согласованность (eventual или weak) может быть приемлема для некоторых сценариев.
Допустимы длительные плановые простои для обслуживания.
5. Экономические и инфраструктурные критерии
Стоимость хранения – ключевой аспект (использование холодных/ледяных хранилищ).
Энергоэффективность: данные могут храниться на медленных дисках (HDD) или ленточных библиотеках.
Возможность автоматического многоуровневого хранения (tiering): перемещение данных на более дешевые носители со временем.
6. Операционные характеристики
Отсутствие конкурентных блокировок (lock/latch contention).
Минимальное логирование транзакций (нет необходимости в PITR за каждый день).
Редкие бэкапы полной копии (раз в квартал/год), так как данные неизменны.
Archive Database является вариантом OLAP профиля, который отличается от него по метрикам DB Time:
Периодичностью нагрузки.
Значениями приращения (дельты) DB Time (ASH), близкими к интервалу сбора метрик. То есть если в интервале 1 час суммарный DB Time (ASH) увеличивается на 1–2 часа – это говорит о том, что запущено несколько единичных аналитических запросов.
Абсолютными значениями DB Time (Commited) существенно меньшими, чем интервал сбора метрик.
Сводная таблица особенностей профилей нагрузки.
Уровень | Параметр | Archive DB | OLTP | HTAP | OLAP/Data Warehouse |
Эксплуатационный | Основная цель | Сохранение, редкие запросы | Транзакционная обработка | Гибридная транзакционная и аналитическая обработка | Бизнес-аналитика |
Запись/Чтение | 1%/99% | 50%/50% (может варьироваться) | от 50%/50% до 10%/90% | 10%/90% (ETL + запросы) | |
Размер операций | Большие пакеты добавления | Одиночные записи | Одиночные и пакетные записи | Пакетная загрузка | |
Типичные запросы | Полный перебор, редкие поиски | Точечный доступ по ключу | Точечный доступ и умеренные агрегации | Агрегации, джойны | |
Требование к времени отклика (latency ) | Минуты/часы допустимы | Миллисекунды | Миллисекунды | Секунды/минуты | |
Изменение данных | Только добавление и локальные фиксы | Интенсивное создание, чтение, обновление, удаление | Интенсивное и пакетное изменение | Обновление пакетами | |
Стоимость хранения | Критически важна | Вторична | Важна | Важна | |
Индексы | Минимум, тяжелые | Много, легкие | Много, легкие и специализированные | Много, специализированные | |
Операционный и конфигурационный | Политика резервного копирования | Раз в квартал, год | Еженедельный FULL бекап, ежедневный инкрементальный | Еженедельный FULL бекап, ежедневный инкрементальный | Еженедельный FULL бекап, ежедневный инкрементальный |
Параллелизм | Однопоточный | Однопоточный | Многопоточный | Многопоточный | |
Длительность сессий | >1440 мин | 5-30 мин | 600-1440 мин | 600-1440 мин | |
Падание в кэш (Shared blocks hit ratio, %) | Около 0% | 100% | От 0 до 100% (зависит от ресурсов и динамики нагрузки) | От 0 до 100% (зависит от ресурсов) | |
Профиль нагрузки | Profile ratio: DB Time (ASH/Commited) | Длительно около 0 или длительно около 1000 | Постоянно около 0 с незначительными скачками не превышающими 300 | Постоянно 300-700 | Постоянно 1000 с возможным падением в 0 когда нагрузки нет. |
DB Time (ASH) абсолютные значения | Приращение выше интервала сбора метрики | Приращение ниже интервала сбора метрики | Приращение ниже интервала сбора метрики | Приращение выше интервала сбора метрики | |
DB Time (Commited) абсолютные значения | Абсолютное значение ниже интервала сбора метрики | Приращение значительно выше интервала сбора метрики | Приращение выше интервала сбора метрики | Абсолютное значение ниже интервала сбора метрики |
Практическая Реализация в PostgreSQL профиля Archive database
Существенные ограничений по ЦПУ и ОЗУ по сравнению с ПРОМ. Либо перемещение на специальные (возможно serverless) платформы, которые или ограничивают ресурсы, или выделяют их динамически по фактической нагрузке. Вероятно, serverless решения окажутся более эффективными с точки зрения суммарно выделенных ресурсов, если таких систем сотни и тысячи, чем множество выделенных серверов (dedicated), так как, например, для «спящих» систем используется 0,25% ядер ЦПУ и минимум памяти около 1 Гб независимо от размеров БД. Однако в случае включения нагрузки ресурсы добавляются в течении нескольких секунд.
Минимизация индексов, ограничивающих быстрый доступ к данным, характерный для OLTP/OLAP.
Перемещения на медленные и дешевые хранилища.
Возможна реализация через таблицы с секционированием по времени на медленных хранилищах.
Что будет, если Archive DB использовать как продуктив (риски)
Как видим из сравнительной таблицы, архивный профиль характеризуется:
Существенными ограничениями по ресурсам, прежде всего ЦПУ, ОЗУ.
Медленными хранилищами данных.
Так же возможно отсутствие каких-то индексов.
Система может быть недоступна часами, но все же через какое-то время гарантированно будет доступна, и это нормальная ситуация.
Бекапы очень редки (раз в квартал, раз в год).
Если вы нагрузите архивную систему как ПРОМ, то БД может попросту не работать из-за недостатка ресурсов, которые мы заранее ограничили. Это может отражаться, например, в высоких LA. Если вы ее случайно повредите, удалите какие-то нужные данные, то ближайший бекап – это квартал или год назад. Такая ситуация может привести к катастрофическим последствиям.
Именно поэтому с точки зрения мониторинга крайне важно своевременно информировать, что Архивная система внезапно начала использоваться не по своему прямому назначению, чтобы прежде всего избежать ее разрушения. А для Архивной БД именно сохранность данных имеет ключевое значение.
Итоги
Я показал, что можно очень быстро оценить состояние БД достаточно простой метрикой, являющейся комбинаций state + wait_event + wait_event_type из представления pg_stat_activity, особенно если у вас есть история этого представления. Хорошее чтение такого компактного графика может избавить от необходимости просмотра множества графиков, чтобы узнать однозначно, что же происходит с БД в динамике.
Также показал, как определить фактический профиль нагрузки БД по двум метрикам DB Time ASH и DB Time Committed. Изменение профиля нагрузки – это не просто информация, а повод для действий либо по доумощению ресурсами, переконфигруации БД, изменения параметров операционной системы, либо оптимизации запросов или структуры БД.
В конце статьи мы достаточно подробно показали особенности профиля Archive Database и его отличие от продуктивных профилей OLAP/OLTP/HTAP и в чем опасность использования Архивной БД как ПРОМ.
Надеюсь, этот подход к мониторингу будет вам полезным и в администрировании ваших систем PostgreSQL. Спасибо за внимание!
