Добавить в корзинуПозвонить
Найти в Дзене
Postgres DBA

PG_EXPECTO 8.1.1 : инцидент PostgreSQL – анализ деградации при простое дисковой подсистемы: влияние памяти и запросов

Многофакторное расследование парадоксальной деградации производительности в среде AstraLinux SE при минимальной утилизации SSD-дисков: доминирование ожиданий DataFileRead, дефицит оперативной памяти и критическая роль двух пользовательских запросов
Max: PG_EXPECTO
GitHub - Комплекс pg_expecto для статистического анализа производительности и нагрузочного тестирования СУБД
Оглавление

Многофакторное расследование парадоксальной деградации производительности в среде AstraLinux SE при минимальной утилизации SSD-дисков: доминирование ожиданий DataFileRead, дефицит оперативной памяти и критическая роль двух пользовательских запросов

Молчание SSD не гарантирует скорости: когда узким местом становятся память и запросы
Молчание SSD не гарантирует скорости: когда узким местом становятся память и запросы
-2

Max: PG_EXPECTO

GitHub - Комплекс pg_expecto для статистического анализа производительности и нагрузочного тестирования СУБД PostgreSQL

Philosophical_instruction_BETA_v5.1.md - Философское ядро + процедурный скелет автономного AI-агента с встроенной самопроверкой. Эпистемология, этика честности, научный метод, think pipeline (CoVe, ToT, Pre-Mortem, Red Teaming, 7 Грехов). Максимальная правдивость, защита от галлюцинаций и prompt injection.

Коллекция промптов для нейросети DeepSeek (на русском языке), предназначенных для анализа и оптимизации производительности СУБД PostgreSQL.

GitFlic - pg_expecto - статистический анализ производительности и ожиданий СУБД PostgreSQL

Глоссарий терминов | Postgres DBA | Дзен

-3

Предисловие

Снижение операционной скорости в условиях промышленной эксплуатации традиционно ассоциируется с насыщением дисковой подсистемы, однако реальная картина отказов нередко оказывается контр-интуитивной. Настоящая работа описывает инцидент, зафиксированный на виртуализированном экземпляре PostgreSQL 15.15 (ОС AstraLinux SE, 8 vCPU Intel Xeon Skylake, 15.61 ГБ ОЗУ), где устойчивое падение пропускной способности на протяжении часа сопровождалось практически полным отсутствием нагрузки на SSD-тома данных и WAL. Целью исследования является идентификация внутренних узких мест СУБД, обусловивших наблюдаемую аномалию, и выработка обоснованных рекомендаций по восстановлению проектных характеристик обслуживания.

Операционная скорость СУБД

-4

Рис.1 График изменения операционной скорости СУБД в ходе инцидента

Инструкция по подготовке аналитического отчета

pg_expecto/sh/performance_reports/incident_report.md at main · pg-expecto/pg_expecto

Аналитический отчет по инциденту производительности СУБД, подготовленный с помощью DeepSeek

Общая информация

  • Система: PostgreSQL 15.15 на AstraLinux SE, 8 vCPU (Intel Xeon Skylake), 15.61 ГБ ОЗУ. Диски: отдельные тома для данных (/data, 2 ТБ), WAL (/wal, 200 ГБ) и логов. Используются SSD с минимальными задержками (<1 мс).
  • Анализируемые периоды: тестовый (12:18–13:18) и инцидентный (13:18–14:18).
  • Основные параметры конфигурации: shared_buffers = 4003MB, effective_cache_size = 12011MB, work_mem = 8MB, maintenance_work_mem = 1000MB, autovacuum_work_mem = 256MB, random_page_cost = 1.1, checkpoint_timeout = 15min, wal_keep_size = 60GB.
  • Ключевое наблюдение: В инцидентный период зафиксировано устойчивое падение операционной скорости СУБД (SPEED) на фоне резкого роста влияния ожиданий ввода-вывода при чтении (DataFileRead). Дисковая подсистема остаётся практически незагруженной, что указывает на внутренние узкие места в PostgreSQL, а не на физические ограничения оборудования.

Ключевые проблемы СУБД и инфраструктуры

☑️Доминирующие ожидания DataFileRead (подтверждено).

  • Единственный значимый тип ожиданий — IO:DataFileRead. В инциденте его корреляция с падением общей производительности стала сильной отрицательной (r = –0.80). Два конкретных запроса формируют 78% всех ожиданий чтения, один из них также вызывает расширение файлов (DataFileExtend).

Острый дефицит свободной оперативной памяти (вероятно).

  • Уровень свободной RAM (free) на обоих периодах не превышает 5% от общего объёма (медиана 418–589 МБ). Это создаёт риск вытеснения страниц PostgreSQL из разделяемой памяти и ухудшения работы файлового кэша ОС. Причина — слишком высокие значения shared_buffers (4 ГБ) и effective_cache_size (12 ГБ), суммарно почти полностью занимающие всю доступную память.

Неоптимальные настройки памяти (вероятно).

  • shared_buffers занимает ~26% ОЗУ, что для системы с таким объёмом памяти может быть избыточным, лишая ОС пространства для кэширования.
  • effective_cache_size задан практически равным всей оперативной памяти, что вводит планировщик в заблуждение: он предполагает высокую доступность данных в кэше, но реальность может быть иной.
  • Низкий work_mem (8 МБ) вынуждает выполнять сортировки и хеш-таблицы на диске, увеличивая читающую нагрузку.

☑️Два проблемных запроса, генерирующих избыточный ввод-вывод (подтверждено).

  • Запросы с хэшами -4120361610817362173 и 2000412135465383132 создают подавляющую часть ожиданий чтения. Второй запрос дополнительно вызывает расширение файлов таблиц/индексов, что указывает на активную вставку данных или неоптимальное управление свободным пространством.

Снижение эффективности буферизации записи в инцидентный период (вероятно).

  • Корреляция между буферным кэшем (buff) и интенсивностью записи на диск данных ослабла, что говорит о возросшей пиковой нагрузке на запись, нарушающей прежний баланс. Это может быть связано с ростом операций расширения файлов и, возможно, с менее эффективной работой фоновых процессов (checkpoint, bgwriter).

Замедление autovacuum без адекватного увеличения обработанных страниц (вероятно).

  • Длительность процессов autovacuum выросла в 2.75 раза, тогда как количество удалённых страниц уменьшилось (97 против 522). Это может свидетельствовать о том, что autovacuum конкурирует с пользовательской нагрузкой за доступ к таблицам или испытывает те же задержки ввода-вывода, что и основные запросы.

Рекомендации по оптимизации СУБД и инфраструктуры

1. Оптимизация запросов-лидеров (подтверждённая необходимость)

Получить и проанализировать планы выполнения (EXPLAIN (ANALYZE, BUFFERS)) для запросов -4120361610817362173 и 2000412135465383132. Обратить внимание на избыточные Seq Scan, сортировки на диске, отсутствие индексов.

Для запроса с DataFileExtend:

  • Проверить частоту операций INSERT/UPDATE, возможно, снизить «горячесть» таблиц через оптимизацию на уровне приложения.
  • Убедиться, что для целевых таблиц выполняются своевременные VACUUM и ANALYZE (текущие агрессивные настройки autovacuum могут не справляться из-за конкуренции).
  • Рассмотреть введение покрывающих индексов (covering indexes), чтобы уменьшить необходимость чтения кучи.

2. Корректировка параметров памяти (вероятно, улучшит ситуацию)

  • ❓shared_buffers: снизить до 2–3 ГБ. Это высвободит память для файлового кэша ОС, который в условиях высоких ожиданий чтения часто эффективнее буферного кэша PostgreSQL.
  • effective_cache_size: установить в значение RAM – shared_buffers – 1 ГБ (ориентировочно 11–12 ГБ). Не суммировать вплотную с shared_buffers.
  • work_mem: увеличить до 16–32 МБ для сокращения сортировок на диске. Важно: предварительно выяснить значение max_connections и оценить пиковое потребление (work_mem * max_connections) — оно не должно превышать доступную память после выделения shared_buffers.
  • maintenance_work_mem: снизить до 512 МБ, если не выполняются регулярные операции по созданию гигантских индексов. Это уменьшит пиковое потребление памяти служебными процессами.

3. Настройка подсистемы записи и WAL (вероятно, снизит нагрузку)

  • Проверить параметр commit_delay (в отчёте есть упоминание commit_delay = 1000, но в исходной конфигурации он не указан). Если установлен, рассмотреть уменьшение до 100–500 или отключение, так как излишняя задержка может накапливать несохранённые данные и повышать требования к WAL.
  • Снизить wal_keep_size с 60 ГБ до более разумного значения (например, 10–20 ГБ). Большой размер резервирует значительный объём WAL, что может косвенно влиять на запись.
  • При допустимости более длительного восстановления после сбоя увеличить checkpoint_timeout до 20–30 минут, чтобы снизить частоту сбросов «грязных» страниц и пиковую нагрузку на I/O.

4. Оптимизация autovacuum (вероятно, повысит эффективность)

  • Проверить autovacuum_vacuum_cost_delay и vacuum_cost_limit. При агрессивных масштаб-факторах пороговая нагрузка может искусственно замедляться. Возможно, увеличить vacuum_cost_limit до 6000–8000 для ускорения очистки.
  • Для таблиц, связанных с проблемными запросами, выполнить внеплановый VACUUM FREEZE или ANALYZE в периоды минимальной нагрузки, чтобы стабилизировать статистику и карту видимости.

5. Инфраструктурные изменения (вероятно, необходимо)

  • Приоритетно рассмотреть увеличение объёма ОЗУ виртуальной машины до 20–24 ГБ. Текущие 15.6 ГБ с учётом нужд ОС и PostgreSQL оставляют крайне малый резерв.
  • При невозможности нарастить память — строго ограничить shared_buffers и work_mem, а также выявить и исключить необязательные процессы на этом хосте.

Необходимая дополнительная информация для продолжения анализа и оптимизации

Для точной настройки и подтверждения гипотез требуется:

  1. Планы выполнения проблемных запросов с EXPLAIN (ANALYZE, BUFFERS, TIMING) для идентификаторов -4120361610817362173 и 2000412135465383132.
  2. Текущее значение max_connections и среднее количество активных соединений в период нагрузки — для безопасного расчёта work_mem.
  3. Уточнение параметра commit_delay (присутствует ли, и если да, то его текущее значение).
  4. Наличие и содержимое параметров vacuum_cost_delay, vacuum_cost_limit для более точной настройки autovacuum.
  5. Графики или статистика по объёму временных файлов (temp_files/temp_bytes из pg_stat_database) за анализируемый период, чтобы косвенно оценить вклад сортировок на диске.
  6. Информация о характере нагрузки: OLTP/OLAP, число одновременных сессий, типичные паттерны вставки/обновления для затронутых таблиц.

Итог: Инцидент вызван не физической перегрузкой дисков, а внутренними ограничениями PostgreSQL, спровоцированными двумя ресурсоёмкими запросами и неоптимальными настройками памяти. Первоочередные шаги — адресная оптимизация запросов и коррекция shared_buffers/work_mem — с высокой вероятностью восстановят производительность до приемлемого уровня. Рекомендуется выполнять изменения поэтапно, контролируя влияние на свободную память и ожидания ввода-вывода.

-5

Общий технический итог

Корреляционный и сравнительный анализ двух смежных временных интервалов (тестового и инцидентного) позволил установить, что доминирующим типом ожиданий выступает IO:DataFileRead, продемонстрировавший сильную отрицательную связь (r = –0.80) с операционной скоростью в период деградации. Два запроса (хэши -4120361610817362173 и 2000412135465383132) генерировали 78% всех событий чтения, причём второй дополнительно инициировал операции расширения файлов (DataFileExtend). Парадокс простоя дисковой подсистемы разрешается совокупностью факторов: острым дефицитом свободной оперативной памяти (медиана ~5% от общего объёма) из-за завышенных значений shared_buffers (4 ГБ) и effective_cache_size (12 ГБ), неоптимально низким work_mem (8 МБ), провоцирующим дисковые сортировки, а также снижением эффективности буферизации записи и замедлением autovacuum.

Физические характеристики накопителей исключены из числа первопричин — инцидент обусловлен исключительно конфигурационными и запросными факторами.

Послесловие

Выполненный анализ подтверждает, что в системах с быстрой дисковой подсистемой внутренние механизмы PostgreSQL и параметры распределения памяти способны выступать лимитирующим звеном, имитируя картину классического I/O-бутылочного горлышка. Практическая ценность полученных результатов заключается в демонстрации детерминированной процедуры дифференциальной диагностики, позволяющей избежать неоправданного расширения аппаратных ресурсов. Дальнейшие шаги предполагают экспериментальную верификацию выдвинутых гипотез: поэтапную коррекцию shared_buffers, effective_cache_size и work_mem под инструментальным контролем метрик свободной памяти, а также оптимизацию планов выполнения проблемных запросов после получения соответствующих отчётов EXPLAIN (ANALYZE, BUFFERS).

Накопление статистики по временным файлам и уточнение параметров стоимости вакуумирования позволят завершить построение замкнутой модели инцидента и перейти к предиктивному мониторингу подобных состояний.