Практическое применение статистического анализа производительности СУБД с использованием pg_expecto v.7: разбор инцидента и верификация гипотез

GitFlic - pg_expecto - статистический анализ производительности и ожиданий СУБД PostgreSQL
Глоссарий терминов | Postgres DBA | Дзен
Предыдущие материалы
Предисловие
Целесообразность применения нейросети DeepSeek для анализа статистических данных и подготовки рекомендаций по итогам инцидентов обусловлена ограниченностью традиционных методов нагрузочного тестирования, нерелевантных в условиях стохастических пиковых нагрузок промышленных систем. В рамках настоящей работы на базе инструментария pg_expecto v.7 продемонстрирована эффективность перехода к статистическому анализу инцидентов PostgreSQL: от идентификации критических факторов до вери��икации гипотез оптимизации. Использование DeepSeek обеспечивает математически обоснованные выводы о причинах деградации производительности, что подтверждает высокую эффективность данного подхода для оперативной диагностики и повышения отказоустойчивости информационных систем.
Шаблон анализа инцидента производительности СУБД
Проанализировать причины инцидента производительности СУБД.
Подготовить рекомендации по оптимизации производительности СУБД по результатам анализа инцидента
Проконтролировать влияние рекомендованных изменений на производительность СУБД при аналогичной нагрузке.
Производительность СУБД

Инцидент производительности СУБД
Операционная скорость - снижается
Ожидания СУБД - растут


1. Результат анализа нейросетью DeepSeek статистических данных по метрикам СУБД и ОС, подготовленных PG_EXPECTO v.7.
Проблемы СУБД
Критическое доминирование IO-ожиданий
В обоих периодах основным типом ожидания является IO (интегральный приоритет вырос с 0.6271 в тесте до 0.7789 в инциденте). Корреляция операционной скорости с IO-ожиданиями отрицательная и статистически значимая (−0.786 в инциденте), что означает: рост ожиданий напрямую снижает производительность.
Один запрос генерирует основную массу ожиданий
QueryID -6237913963540934095 вызывает 87% всех IO-ожиданий (в тесте — 87.23%, в инциденте — 87.37%). События: DataFileRead, DataFileWrite, SlruRead. Это указывает на конкретный проблемный запрос с интенсивными операциями чтения/записи данных и обращением к WAL (SlruRead).
Запись стала главным узким местом
В тестовом отрезке операционная скорость почти полностью определялась объёмом записанных блоков (R² = 0.95). В инциденте также сохраняется высокая корреляция скорости с записанными блоками (R² = 0.65), а грязные блоки сильно коррелируют с ожиданием IO (R² = 0.76) и с записью на диск (R² = 0.62). Это говорит о неспособности фоновых процессов своевременно сбрасывать грязные страницы.
Рост чтений с диска при высоком hit ratio
Несмотря на hit ratio shared buffers выше 99%, в инциденте появилась сильная корреляция операционной скорости с прочитанными блоками (R² = 0.73). Это означает, что даже 1% чтений, не попавших в кеш, создаёт непропорционально высокую нагрузку из-за большого объёма данных или неэффективных сканов.
Чрезмерное количество подключений
Параметр max_connections = 3000 при 8 ядрах CPU и 7.5 ГБ RAM создаёт избыточное потребление памяти и увеличивает накладные расходы на переключение контекста. Корреляции cs с us и in, хотя и высокие, имеют пониженный R² в инциденте, что указывает на смешанную природу загрузки.
Агрессивные настройки автовакуума
autovacuum_naptime = 1s, низкие scale_factor, autovacuum_max_workers = 4 могут вызывать частые сканирования и дополнительные IO-операции, усугубляя общую дисковую нагрузку.
Проблемы инфраструктуры
Острейший дефицит оперативной памяти
Свободная RAM составляет менее 5% на протяжении 100% времени инцидента (медиана свободной памяти — всего 119 МБ при 7.5 ГБ). Это приводит к вытеснению страничного кеша и росту обращений к диску, хотя сам свопинг не используется.
Лавинообразный рост процессов в состоянии uninterruptible sleep (procs b)
Количество процессов, заблокированных в ожидании IO, выросло с медианы 128 в тесте до 175 в инциденте, с сильным трендом (R² = 0.99, угол наклона 44.5). Это прямое следствие неспособности дисковой подсистемы обслуживать запросы.
Перегрузка очереди выполнения (procs r)
Очередь процессов, готовых к выполнению, превышает количество ядер CPU (8) в 100% времени. При этом CPU простаивает в ожидании IO (wa > 10% постоянно). Процессы не могут получить CPU, потому что заблокированы на IO, но планировщик держит их в очереди.
Высокий процент времени ожидания IO (wa)
Процент простоя CPU в ожидании IO превышает 10% весь период инцидента (достигая 33%). Это свидетельствует о том, что дисковая система не успевает обрабатывать поток запросов.
Корреляция грязных страниц с ожиданием IO
В инциденте размер грязных страниц сильно коррелирует с wa (R² = 0.88) и умеренно с bo (R² = 0.52). Это говорит о том, что механизм фоновой записи не справляется с потоком изменений: страницы накапливаются, и backend-процессы вынуждены синхронно сбрасывать их, блокируясь.
Недостаточная пропускная способность дисковой подсистемы
Несмотря на отдельные диски для WAL и данных, система не выдерживает пиковую нагрузку на запись. Виртуальные диски, вероятно, разделяют общую очередь ввода-вывода с другими виртуальными машинами на гипервизоре.
Параметры ядра dirty_ могут быть неоптимальны
vm.dirty_ratio = 10% (около 750 МБ) — лимит не достигается (реальные dirty pages до 16 МБ), но vm.dirty_expire_centisecs = 3000 (30 секунд) заставляет сбрасывать страницы по таймеру, а диск не успевает. Это приводит к росту wa.
Рекомендации по итогам анализа инцидента
Рекомендации по оптимизации СУБД
1.Оптимизировать проблемный запрос
Провести детальный разбор запроса с queryid -6237913963540934095:
Проанализировать план выполнения, выявить операции с полным сканированием таблиц или индексов, приводящие к DataFileRead/Write.
Проверить, используются ли индексы, нет ли избыточных сортировок или хеш-соединений, требующих записи во временные файлы.
Рассмотреть возможность партиционирования больших таблиц или изменения логики приложения для снижения IO-нагрузки.
2.Снизить количество одновременных подключений
Уменьшить max_connections до разумного значения (например, 300–500) и использовать пул соединений (PgBouncer) для эффективного распределения нагрузки. Это сократит потребление памяти и уменьшит конкуренцию за ресурсы.
3.Настроить параметры контрольных точек
Увеличить checkpoint_timeout до 15–30 минут и max_wal_size до 64–96 ГБ, чтобы сгладить пиковые нагрузки на запись. Отслеживать статистику pg_stat_bgwriter — buffers_checkpoint не должен резко превышать buffers_clean.
4.Отрегулировать фоновую запись
Увеличить bgwriter_lru_maxpages до 800–1000, чтобы фоновый писатель успевал сбрасывать больше грязных страниц за цикл.
Уменьшить bgwriter_delay до 5–10 мс (оставить как есть, но контролировать эффективность).
Увеличить bgwriter_lru_multiplier до 4–6, чтобы более агрессивно предвосхищать потребности.
5.Настроить автовакуум
Увеличить autovacuum_naptime до 5–10 секунд, чтобы снизить частоту запусков.
Подобрать scale_factor и threshold под реальную скорость обновления строк (например, autovacuum_vacuum_scale_factor = 0.05, autovacuum_vacuum_threshold = 1000).
Ограничить autovacuum_max_workers до 2–3, чтобы они не конкурировали с основной нагрузкой.
6.Оптимизировать кеширование для чтения
Несмотря на высокий hit ratio, следует проанализировать, какие именно объекты не попадают в кеш. Возможно, увеличение shared_buffers до 5–6 ГБ (если позволит ОС) поможет удержать больше данных, но нужно оставить память для ОС и файлового кеша.
Рекомендации по оптимизации инфраструктуры
1.Увеличить объем оперативной памяти
Так как текущая загрузка упирается в IO, добавление RAM позволит расширить файловый кеш ОС и, возможно, увеличить shared_buffers, снижая потребность в дисковых операциях. Рекомендуется минимум 16–32 ГБ для такой нагрузки.
2.Оптимизировать параметры ядра Linux
Уменьшить vm.dirty_expire_centisecs до 1500–2000 (15–20 секунд), чтобы страницы сбрасывались быстрее и не накапливались.
Увеличить vm.dirty_background_ratio до 10% и vm.dirty_ratio до 20–25%, чтобы дать системе больше времени для фоновой записи и избежать синхронных сбросов, но только после анализа скорости дисков.
Проверить планировщик ввода-вывода: для виртуальных дисков рекомендуется none (или noop), для физических SSD — mq-deadline.
Установить vm.swappiness = 1 (уже установлено) — оставить, чтобы избежать нежелательного свопирования.
Эти меры помогут стабилизировать производительность и предотвратить дальнейшую деградацию. Первоочередное внимание следует уделить оптимизации проблемного запроса и увеличению оперативной памяти.
2.Применение рекомендованных изменений СУБД и ОС
1.Настроить параметры контрольных точек
Увеличить checkpoint_timeout до 15–30 минут и max_wal_size до 64–96 ГБ, чтобы сгладить пиковые нагрузки на запись.
2.Отрегулировать фоновую запись
Увеличить bgwriter_lru_maxpages до 800–1000, чтобы фоновый писатель успевал сбрасывать больше грязных страниц за цикл.
Уменьшить bgwriter_delay до 5–10 мс (оставить как есть, но контролировать эффективность).
Увеличить bgwriter_lru_multiplier до 4–6, чтобы более агрессивно предвосхищать потребности.
3.Оптимизировать параметры ядра Linux
Уменьшить vm.dirty_expire_centisecs до 1500–2000 (15–20 секунд), чтобы страницы сбрасывались быстрее и не накапливались.
Увеличить vm.dirty_background_ratio до 10% и vm.dirty_ratio до 20–25%, чтобы дать системе больше времени для фоновой записи и избежать синхронных сбросов, но только после анализа скорости дисков.
3. Анализ нейросетью DeepSeek влияние изменений на производительность СУБД при аналогичной нагрузке.

Настройки СУБД PostgreSQL
checkpoint_timeout увеличен с 5 min до 30 min – для более редких, но менее пиковых контрольных точек.
max_wal_size повышен с 32 GB до 64 GB – чтобы контрольные точки могли растягиваться во времени без преждевременного заполнения WAL.
bgwriter_lru_maxpages поднят с 400 до 800 – фоновый писатель теперь может сбрасывать больше грязных страниц за цикл.
bgwriter_lru_multiplier увеличен с 4 до 6 – более агрессивное предвосхищение потребностей в чистых буферах.
bgwriter_delay планировалось уменьшить с 10 ms до 5 ms, но изменение не удалось из-за ограничения (минимальное значение 10 ms).
Настройки ядра Linux (vm)
vm.dirty_background_ratio поднят с 5% до 10% – фоновый сброс грязных страниц начинается при большем заполнении памяти.
vm.dirty_ratio увеличен с 10% до 20% – принудительная синхронная запись отодвинута, давая больше времени на фоновый сброс.
vm.dirty_expire_centisecs уменьшен с 3000 (30 с) до 1500 (15 с) – страницы быстрее признаются устаревшими и подлежат записи.
vm.dirty_writeback_centisecs, vm.swappiness и остальные параметры ядра остались без изменений.
Итоговые существенные различия метрик производительности СУБД и инфраструктуры до и после применения рекомендованных настроек
Операционная скорость (SPEED)
Медиана незначительно снизилась: с ~1 045 тыс. до ~1 011 тыс. (в пределах статистической погрешности).
Общие ожидания СУБД (WAITINGS)
Медиана немного уменьшилась: с ~746 тыс. до ~734 тыс. (‑1,6%).
Тренды vmstat (качество и скорость изменений)
procs → r (очередь на выполнение):
До: R²=0,83, скорость изменения 35,37 (очень высокий негативный тренд).
После: R²=0,47 (модель стала хуже), скорость снизилась до 16,16 (умеренный тренд) – положительная динамика, хотя абсолютные значения r выросли (медиана с 10 до 13).
procs → b (ожидание I/O):
До: R²=0,98, скорость 43,76 (критический рост).
После: R²=0,97, скорость 43,46 (столь же высокая) – проблема сохраняется.
cpu → wa (ожидание I/O): в обоих случаях позитивный тренд (улучшение), но классифицируется как «шум».
Относительные показатели (% времени превышения порогов)
r > ядер CPU: вырос с 66,7% до 82,2% – ухудшение (очередь процессов стала чаще превышать количество ядер).
wa > 10% и b > ядер CPU: остались на уровне 100% времени – дисковая подсистема по-прежнему перегружена.
свободная RAM < 5%: также 100% – память остаётся узким местом.
Грязные страницы (dirty pages)
Медиана размера грязных страниц выросла с ~18 МБ до ~30 МБ.
Ключевой запрос
По-прежнему один и тот же queryid (-6237913963540934095) вызывает ~87% всех ожиданий I/O, количество вызовов даже немного увеличилось (с 19,1 M до 19,6 M).
Сравнительный статистический анализ (коэффициенты корреляции и регрессии)
Связь операционной скорости с записанными блоками
До: корреляция 0,9856, R²=0,97 (ALARM).
После: корреляция 0,9920, R²=0,98 – ещё выше, зависимость от записи на диск осталась критической.
Корреляция dirty pages size с wa (ожидание I/O)
До: 0,9695, R²=0,94 (очень сильная).
После: 0,8815, R²=0,78 (снизилась, но всё ещё значима) – положительный эффект настроек VM.
Корреляции с bo (блоки, записанные на устройства)
IO и bo: была значимая (0,6761, R²=0,46) – после изменений отсутствует.
Записанные блоки и bo: была 0,7914 (R²=0,63) – после отсутствует.
Грязные блоки и bo: была слабая (0,6186, R²=0,38) – после отсутствует.
Это говорит о том, что запись стала более равномерной, пиковые сбросы перестали жёстко коррелировать с дисковыми операциями.
Корреляции контекстных переключений (cs)
cs и sy (system time): R² вырос с 0,78 до 0,89 – ядро стало тратить больше времени на переключения контекста относительно системного времени.
cs и us (user time) и cs и in (прерывания) остались на очень высоком уровне (R²>0,95).
Индекс приоритета корреляции (CPI)
dirty pages – wa снизился с 0,9518 до 0,7810 – переместился с 4‑го на 6‑е место в рейтинге, что подтверждает ослабление проблемы.
IO – bi (чтения) исчез из списка значимых корреляций (был 0,5343).
Анализ эффективности рекомендованных нейросетью настроек и итоговое влияние на производительность СУБД
Положительные эффекты
Уменьшилась корреляция между накоплением грязных страниц и простоями CPU в ожидании I/O (wa).
Исчезла прямая связь между объёмом записанных блоков PostgreSQL и фактической записью на диск (bo) – контрольные точки и фоновый writer работают более плавно.
Тренд роста очереди на выполнение (r) замедлился, хотя абсолютные значения выросли.
Отрицательные/нейтральные аспекты
Основная проблема – зависимость производительности от записи на диск – не устранена (корреляция скорости с записанными блоками осталась крайне высокой).
Процессы в непрерываемом сне (b) продолжают расти с прежней скоростью, а процент времени с превышением порогов wa и b остаётся 100%.
Медиана операционной скорости немного снизилась, что может быть следствием изменения характера нагрузки (рост числа вызовов проблемного запроса).
Вывод об эффективности
Рекомендации частично достигли цели: сгладили пиковые сбросы грязных страниц и уменьшили негативное влияние накопления dirty pages на ожидания.
Однако они не затронули корень проблемы – неэффективный запрос select scenario1(), на который приходится 87% всех ожиданий I/O.
Изменения в настройках ОС и СУБД дали локальные улучшения, но не смогли компенсировать недостатки прикладного уровня.
Для дальнейшей оптимизации необходимо:
Исследовать и оптимизировать запрос queryid (-6237913963540934095) (индексы, переписывание, изменение логики).
Рассмотреть возможность аппаратного ускорения дисковой подсистемы (например, размещение WAL на NVMe).
Продолжить мониторинг и при необходимости скорректировать bgwriter_delay (если позволит версия) или параметры автоочистки.
Послесловие
Практическое применение методологии статистического анализа на базе pg_expecto v.7 позволило не только идентифицировать критические факторы деградации производительности (доминирование IO-ожиданий, дефицит памяти, неэффективный запрос), но и количественно верифицировать эффект от предложенных изменений. Корреляционно-регрессионный анализ доказал, что настройки параметров ядра и СУБД привели к снижению зависимости между накоплением грязных страниц и простоями CPU, а также к более равномерной записи на диск. Вместе с тем, сохранение высокой корреляции операционной скорости с объемом записанных блоков и неизменная доля ожиданий по проблемному запросу указывают на необходимость дальнейшей оптимизации на прикладном уровне.
Таким образом, представленная методология обеспечивает объективную основу для принятия решений и позволяет отделить результаты целенаправленных изменений от фоновых колебаний системы, что подтверждает ее ценность как инструмента повседневной практики сопровождения высоконагруженных СУБД.
