Сравнительный анализ двух часовых интервалов: неизменные shared_buffers и стоимость планов, но падение query‑level hit ratio с 93,5 % до 81,8 %, рост физических чтений в 2,7 раза и появление Seq Scan для ресурсоёмких запросов.
GitHub - Комплекс pg_expecto для статистического анализа производительности и нагрузочного тестирования СУБД PostgreSQL
Philosophical_instruction_BETA_v5.1.md - Философское ядро + процедурный скелет автономного AI-агента с встроенной самопроверкой. Эпистемология, этика честности, научный метод, think pipeline (CoVe, ToT, Pre-Mortem, Red Teaming, 7 Грехов). Максимальная правдивость, защита от галлюцинаций и prompt injection.
GitFlic - pg_expecto - статистический анализ производительности и ожиданий СУБД PostgreSQL
Глоссарий терминов | Postgres DBA | Дзен
Предисловие
Миграция СУБД PostgreSQL на более новую версию часто ассоциируется с ожиданием повышения производительности или, как минимум, сохранения достигнутого уровня эффективности. Однако представленный в работе кейс демонстрирует противоположную ситуацию: после перехода с PostgreSQL 15 на 17 при идентичной пользовательской нагрузке (изменение числа запросов менее 1 %) наблюдается трёхкратное увеличение среднего времени выполнения запроса и многократный рост операций ввода-вывода. В статье приведены результаты сравнительного анализа конфигурационных параметров, агрегированных метрик нагрузки и планов выполнения запросов для двух часовых интервалов на версиях 15 и 17. Цель анализа — выявить наиболее вероятные причины деградации и предложить способы их подтверждения или опровержения.
Задача
- Выполнить сравнительный анализ конфигурации и производительности СУБД по данным раздела отчета pgpro_per "Top SQL by elapsed time (SQL-запросы с наибольшей длительностью)".
- Сформулировать и уточнить гипотезу о причинах проблем производительности СУБД после обновления версии СУБД с 15 до 17
Входные данные для анализа
- Период 1 : pgpro_pwr_5635_5636.clear.html - 2026-04-10 09:00-10:00 : Версия 15
- Период 2 : pgpro_pwr.93-94.clear.html - 2026-04-24 09:00-10:00 : Версия 17
1. Ключевые отличия конфигурационных параметров
Источник: table.result.txt. (Таблица соответствия конфигурационных параметров между отчетами)
Отсутствие параметра в таблице означает, что его значение не изменялось между периодами (Подтверждено пользователем). Таким образом, критически важные shared_buffers, effective_cache_size, work_mem, maintenance_work_mem, random_page_cost, seq_page_cost, checkpoint_timeout, max_wal_size и другие не перечисленные параметры идентичны в обоих периодах.
Ниже — только параметры, изменившиеся между периодами.
☑️online_analyze.enable
- on → off
- (Подтверждено) Автоматический сбор статистики при DML-операциях отключён во втором периоде.
☑️auto_explain (группа параметров)
(Подтверждено)
Период 1:
- модуль не активирован (session_preload_libraries пусто, все auto_explain.* = N/A).
Период 2:
- session_preload_libraries = auto_explain
- auto_explain.log_min_duration = -1 ms — планы всех запросов записываются в лог
- auto_explain.log_analyze = on,
- log_buffers = on,
- log_timing = on,
- log_verbose = on — максимальная детализация
- auto_explain.sample_rate = 1 — логируется 100% запросов
- Это создаёт постоянную дополнительную нагрузку на CPU и дисковую подсистему (запись объёмных логов).
☑️plan_cache_lru_memsize
- 8192 kB → 102400 kB
- (Подтверждено) Увеличен кэш планов в 12.5 раз.
☑️wal_keep_size
- 128 MB → 30720 MB
- (Подтверждено) Значительное увеличение резервируемого места под WAL.
☑️wal_buffers
- 16 MB → 64 MB
- (Подтверждено) Увеличен буфер WAL.
☑️wal_compression
- pglz → lz4
- (Подтверждено) Изменён алгоритм сжатия WAL.
☑️wal_writer_delay
- 200 ms → 100 ms
- (Подтверждено) Вдвое более частый сброс WAL-буфера на диск.
☑️write_page_cost
- N/A (в Postgres Pro 15 параметр отсутствовал) → 5
- (Подтверждено) Установлен параметр стоимости записи страницы. ℹ️(Задаёт приблизительную стоимость сброса страниц временных таблиц на диск. Значение по умолчанию — 5.0. Обратите внимание, что этот параметр работает только в том случае, если включён enable_parallel_temptables.)
☑️jit
- on → off
- (Подтверждено) JIT-компиляция отключена.
☑️autoprepare_threshold / autoprepare_for_protocol
- 0 / all → 2 / simple
- (Подтверждено) Изменён порог и протокол автоматической подготовки запросов.
☑️max_parallel_autovacuum_workers
- N/A → 0
- (Подтверждено) Параллельный autovacuum отключён.
☑️vacuum_buffer_usage_limit
- N/A → 2048 kB
- (Подтверждено) Ограничен буфер, используемый vacuum.
☑️log_lock_waits
- off → on
- (Подтверждено) Включено логирование ожиданий блокировок.
2. Ключевые отличия показателей «Load distribution»
Доминирующая база данных — DB-4. Оба отчётных интервала имеют одинаковую длительность (1 час), что позволяет прямое сравнение абсолютных величин и вычисление производных метрик.
2.1. Абсолютные значения и интенсивность (для DB-4)
Количество выполненных запросов (Executed count)➡️
- 6 661 587 → 6 706 321 (+0.67%)
- Интенсивность: ~1850 запр/с → ~1863 запр/с
- (Подтверждено) Нагрузка по числу запросов практически не изменилась.
Общее время выполнения (Total time)⬆️
- 6808.58 с → 22384.31 с (рост в 3.29 раза)
- Средняя параллельность (Total time / длительность): 1.89 → 6.22
- (Подтверждено) Резкое увеличение времени активности запросов.
Среднее время выполнения одного запроса (Total time / Executed count)⬆️
- ~1.02 мс → ~3.34 мс (рост в 3.27 раза)
- (Подтверждено) Каждый запрос в среднем стал выполняться втрое дольше.
Время ввода-вывода (I/O time)⬆️
- 1034.72 с → 13879.71 с (рост в 13.4 раза)
- Доля I/O в общем времени: ~15.2% → ~62.0%
- Средняя занятость I/O: 0.29 с/с → 3.86 с/с
- (Подтверждено) Основным компонентом времени выполнения стали операции с диском.
- Среднее время I/O на один запрос
- ~0.155 мс → ~2.07 мс (рост в 13.4 раза)
- (Подтверждено)
Прочитанные разделяемые блоки с диска (Shared blocks read)⬆️
- 72 026 559 → 192 575 854 (рост в 2.67 раза)
- Интенсивность чтения: ~20 000 блоков/с → ~53 500 блоков/с
- (Подтверждено) Физическое чтение резко выросло.
- Среднее число прочитанных с диска блоков на запрос
- ~10.8 → ~28.7 (рост в 2.66 раза)
- (Подтверждено) Запросы стали читать существенно больше данных с диска.
Кэш-хит для запросов (query-level hit ratio, рассчитан из Load distribution)⬇️
- 93.5% → 81.8% (снижение на 11.7 п.п.)
- (Подтверждено) Рассчитан как (Blocks fetched – Shared blocks read) / Blocks fetched.
⚠️Значительное падение доли чтений из буферного кэша.⚠️
ℹ️Общий кэш-хит базы данных DB-4 (pg_stat_database, предоставлен пользователем)
- 94.43% → 86.97% (снижение на 7.46 п.п.)⬇️
- (Подтверждено) Общий hit ratio упал заметно меньше, чем hit ratio по запросам. Это указывает, что деградация сконцентрирована именно в пользовательской нагрузке, а не в системных процессах (фоновая запись, контрольные точки, vacuum).
Сгенерированный WAL⬆️
- 6.88 млрд байт → 11.90 млрд байт (рост в 1.73 раза)
- Интенсивность: ~1.91 МБ/с → ~3.31 МБ/с
- (Подтверждено)
Temp/Local blocks written⬇️
- 3.70 млн → 2.37 млн (снижение на 36%)
- (Подтверждено) Меньше операций временной записи.
Cache resets⬆️⬆️
- 1 → 79 (многократный рост)
- (Подтверждено) Частые сбросы статистики (pg_stat_statements) или аварийные перезапуски. Сами по себе обнуляют накопленные счётчики и обесценивают статистику планировщика.
2. Гипотеза о влиянии конфигурационных параметров на показатели нагрузки
Уровень-2 (Вероятно, но требует проверки):
Основная причина многократного роста I/O (чтения) и падения cache hit ratio при практически неизменном количестве запросов и идентичных параметрах пула буферов (shared_buffers) и стоимостных констант (random_page_cost, seq_page_cost) — устаревание статистики планировщика из-за отключения online_analyze.enable в сочетании с частыми сбросами кэша статистики ⚠️(Cache resets = 79).⚠️
ℹ️Без актуальных гистограмм и списков частых значений планировщик недооценивает селективность условий и систематически выбирает неоптимальные планы — прежде всего последовательные сканирования (Seq Scan) больших таблиц вместо индексных доступов. Это вызывает рост физических чтений (увеличение shared_blks_read и I/O time, падение query-level hit ratio на 11.7 п.п. при падении общего hit ratio БД только на 7.46 п.п.).
ℹ️Дополнительная фоновая нагрузка от auto_explain (логирование полных планов с таймингами и буферами для каждого запроса) создаёт существенные накладные расходы на CPU и запись логов, что вносит вклад в рост Total time, но не объясняет специфического увеличения физических чтений с диска. Она выступает сопутствующим фактором, усугубляющим общую деградацию производительности.
Альтернативные факторы (Уровень-3 — Предположение):
- Появление параметра write_page_cost = 5 могло исказить стоимостную оценку операций записи в планировщике, однако механизм его влияния на выбор между Seq Scan и Index Scan не документирован в предоставленных данных и требует изучения документации вендора.
- Отключение параллельного autovacuum и ограничение его буфера потенциально замедляют очистку мёртвых строк, что может увеличивать объём просматриваемых данных при сканированиях, но не объясняет столь резкое падение hit ratio в пределах одного часа.
Последовательность рассуждений и тезисы, использованные при формулировании гипотезы
Нагрузка по числу запросов стабильна
- Executed count отличается менее чем на 1% при одинаковой часовой длительности. Следовательно, деградация не вызвана ростом количества выполняемых операторов. (Подтверждено)
⬇️
Ключевые параметры кэширования и стоимостей не изменялись
- shared_buffers, effective_cache_size, work_mem, random_page_cost, seq_page_cost идентичны в обоих периодах. Это исключает версию, что ухудшение связано с изменением лимитов памяти или базовых стоимостных констант планировщика. (Подтверждено)
⬇️
Симптомы указывают на смену планов запросов
- Резкий рост shared_blks_read и I/O time при стабильном количестве запросов и снижении query-level hit ratio с 93.5% до 81.8% — типичная картина перехода от эффективных индексных доступов к полным сканированиям таблиц. Общий hit ratio БД упал меньше (с 94.43% до 86.97%), подтверждая, что проблема локализована именно в пользовательских запросах, а не в фоновых процессах. (Подтверждено)
⬇️
Из изменённых параметров прямое влияние на планировщик оказывают online_analyze.enable и, возможно, write_page_cost
- online_analyze отвечает за оперативное обновление статистики при DML-операциях. Его отключение в сочетании с 79 сбросами кэша практически гарантирует работу планировщика на устаревших или пустых гистограммах, что ведёт к некорректной оценке селективности и выбору Seq Scan. (Вероятно)
⬇️
Дополнительная нагрузка от auto_explain объясняет часть роста Total time, но не рост чтений
- Запись полных планов всех запросов генерирует значительный объём логов, нагружая дисковую подсистему и CPU, однако не может быть причиной специфического увеличения shared_blks_read на запрос. Это сопутствующий фактор, усиливающий общую деградацию. (Предположение)
➡️Формулировка итоговой гипотезы
- Наиболее вероятной причиной является устаревание статистики планировщика из-за отключения online_analyze и множественных сбросов кэша, вызвавшее массовый переход на последовательные сканирования. (Вероятно)
Способы подтверждения и опровержения гипотезы
Анализ планов запросов (ключевой метод)
- Используя pg_stat_statements или уже собранные логи auto_explain, найти top-N запросов по shared_blks_read за оба периода и сравнить их планы выполнения. Наличие Seq Scan на крупных таблицах в Период 2, где ранее фиксировался Index Scan, станет прямым подтверждением гипотезы. Если планы идентичны, а рост чтений вызван увеличением объёма данных — гипотеза опровергается, и причина в росте таблиц. (Уровень-2)
Проверка актуальности статистики
- Запрос к pg_stat_user_tables: сравнить last_analyze, n_mod_since_analyze, last_autoanalyze. Большое количество модификаций без своевременного анализа напрямую докажет устаревание статистики. (Уровень-2)
➡️Контролируемый эксперимент с включением online_analyze⬅️
- В тестовой среде или в изолированном временном окне промышленной системы включить online_analyze = on (при сохраняющихся прочих параметрах Периода 2) и измерить shared_blks_read, I/O time, hit ratio. Снижение физических чтений станет прямым доказательством влияния статистики. (Уровень-2)
Оценка вклада auto_explain
- Изменить log_min_duration на разумный порог (например, 1000 мс) или временно отключить auto_explain (при тех же online_analyze = off) и сравнить Total time и I/O time. Это позволит количественно отделить накладные расходы логирования от деградации планов. (Уровень-2)
Анализ wait events и системной статистики
- Если профиль ожиданий Периода 2 насыщен событием DataFileRead при высокой утилизации диска, а WALWrite не доминирует, это согласуется с версией избыточных чтений. Для полноты картины необходимы данные pgpro_pwr по ожиданиям и показатели iostat за оба периода. (Неизвестно — данные не предоставлены)
➡️Расследование причин Cache resets⬅️
- Проверить лог PostgreSQL на наличие падений/перезапусков, ошибок или ручных вызовов pg_stat_reset(). Если сбросы вызваны нестабильностью — требуется устранение корневой причины; если ручные — пересмотреть регламент администрирования, так как они обнуляют накопленную статистику планировщика. (Уровень-3)
Ограничения анализа (Неизвестно):
- Размеры таблиц и их рост между периодами — невозможно исключить, что объём данных увеличился, хотя за две недели это менее вероятно как основная причина троекратного падения hit ratio.
- Планы запросов, wait events, данные ОС (iostat, vmstat) — без них выводы о точной причине остаются вероятностными.
- Семантика параметра write_page_cost в используемой сборке Postgres Pro Enterprise 17.7.1 — требует документации вендора.
ℹ️Допущение о неизменности не перечисленных параметров и одинаковая часовая длительность интервалов позволили исключить из рассмотрения основные конфигурационные лимиты и нормировать нагрузку, что ➡️существенно сузило круг возможных причин до online_analyze, сбросов кэша и побочного эффекта auto_explain.⬅️
3. Сравнительный анализ планов выполнения по разделу "Top executed time"
Период наблюдения 09:00 – 10:00 :
- Период 1(P1) (отчёт‑5635_5636): 2026-04-10
- Период 2(P2) (отчёт‑93‑94): 2026-04-24
Сопоставление выполнено по Query ID из queryid‑2.txt. Результаты:
Запросы к _InfoRg12756 + временная таблица (8 штук)
- Планы в обоих периодах структурно идентичны: Nested Loop с Seq Scan по временной таблице и Index Scan по _InfoRg12756 с использованием индекса _inforg12756_1. Никаких признаков появления Seq Scan на основной таблице.
- Статус: Подтверждено — деградации планов для этой группы не наблюдается.
Запрос 12e2db113ff929b0 (P2) / b932f4ddf25919b4 (P1) к _InfoRg12488
- P2: зафиксированы три варианта плана: Seq Scan, Bitmap Heap Scan, Index Scan.
- P1: зафиксированы два варианта: Index Scan, Bitmap Heap Scan. Вариант с Seq Scan отсутствует.
- Статус: Подтверждено — в P2 появился план с полным сканированием таблицы, которого не было в P1. Это прямое свидетельство того, что при некоторых значениях параметров планировщик выбирает Seq Scan вместо индексного доступа.
- Запрос b9cbf749af16caf2 (P2) / fa63b14b886156e6 (P1) к _InfoRg13163
- P2: только Index Scan.
- P1: Seq Scan и Index Scan.
- Картина обратная — Seq Scan присутствовал в P1, но не в P2.
- Статус: Подтверждено — план в P2 не ухудшился, а формально улучшился. Однако без данных о доле этого запроса в общей нагрузке по чтению невозможно судить о его влиянии на общий I/O.
Запрос 22fb79dbb23e1e4 (P2) / b0088efd05addab2 (P1) к _InfoRg12488
- Оба периода — Index Scan. Изменений нет.
- Статус: Подтверждено.
Остальные запросы (INSERT, SELECT из _Reference15235, и пр.)
- Планы отсутствуют в одном из периодов или неинформативны для сравнения.
ℹ️Интерпретация в свете гипотезы analyze‑2.txt
Гипотеза утверждала, что отключение online_analyze и множественные сбросы статистики (Cache resets = 79) ведут к выбору планировщиком неоптимальных Seq Scan на больших таблицах, что вызывает рост физических чтений. ➡️Данные планов частично поддерживают эту версию:
- Для запроса к _InfoRg12488 (присутствует в top‑SQL по времени выполнения, следовательно, вероятно, весомый) действительно зафиксировано появление Seq Scan в P2, которого не было в P1. Это согласуется с гипотезой об устаревании статистики и ошибочной оценке селективности.
- Группа запросов к _InfoRg12756, составляющая большинство сопоставленных запросов, не демонстрирует изменений планов. Следовательно, деградация, по-видимому, сконцентрирована в отдельных запросах, а не носит массового характера. Это объяснимо: устаревшая статистика вредит прежде всего тем запросам, где селективность фильтров критична для выбора между Index Scan и Seq Scan.
- Единичный обратный пример (_InfoRg13163) не опровергает гипотезу, если данный запрос не является доминирующим по вкладу в shared_blks_read.
Уточнённая гипотеза (Уровень‑2: Вероятно, но требует проверки)
Основная причина роста I/O и падения cache hit ratio — локальное ухудшение планов для отдельных ресурсоёмких запросов (прежде всего к _InfoRg12488) из‑за работы планировщика на устаревшей статистике. Это вызвано отключением online_analyze.enable и массовыми сбросами кэша статистики (Cache resets = 79). Дополнительная фоновая нагрузка от auto_explain (логирование всех запросов с полным analyze) вносит вклад в общее время выполнения, но не объясняет специфического роста физических чтений.
Последовательность рассуждений и тезисы
Общая нагрузка по количеству запросов стабильна
- Executed count изменился менее чем на 1%.
- Статус: Подтверждено (из analyze‑2.txt).
⬇️
Ключевые параметры кэша и стоимости не менялись
- shared_buffers, effective_cache_size, work_mem, random_page_cost, seq_page_cost идентичны.
- Статус: Подтверждено (из table.result.txt).
⬇️
Резкий рост физических чтений и падение query‑level hit ratio
- Shared blocks read вырос в 2.67 раза, I/O time в 13.4 раза, hit ratio упал с 93.5% до 81.8%.
- Статус: Подтверждено (из analyze‑2.txt).
- Сравнение планов выявило появление Seq Scan в P2 для запроса к _InfoRg12488
- В P1 такой план не зафиксирован, в P2 — зафиксирован.
- Статус: Подтверждено (из plan‑3/plan‑4).
⬇️
Группа наиболее часто встречающихся запросов (_InfoRg12756) сохранила планы
- Значит, деградация не всеобщая, а сосредоточена в отдельных запросах.
- Статус: Подтверждено.
⬇️
Из изменённых параметров прямо на планировщик влияют online_analyze.enable и, возможно, write_page_cost
- Отключение online_analyze при 79 сбросах кэша практически гарантирует использование устаревших гистограмм, что ведёт к ошибкам оценки селективности и выбору Seq Scan. Появление write_page_cost = 5 могло дополнительно исказить стоимостную модель, но его семантика не документирована.
- Статус: Вероятно для online_analyze, Предположение для write_page_cost.
⬇️
auto_explain с log_min_duration = -1 создаёт фоновую нагрузку, но не вызывает избирательный рост чтений
- Статус: Вероятно (не может быть причиной троекратного роста shared_blks_read на запрос).
Дополнительные способы подтверждения/опровержения гипотезы
Идентификация top‑N запросов по shared_blks_read в каждом периоде
- Используя pg_stat_statements (если сбросы не обнулили данные) или логи auto_explain P2, выделить запросы с наибольшим абсолютным приростом чтений. Проверить их планы. Если среди них окажется 12e2db113ff929b0 с Seq Scan — сильное подтверждение. Если прирост дают другие запросы без изменений планов — гипотезу придётся пересмотреть.
- Статус: Неизвестно — данные не предоставлены.
Детальный анализ параметров вызова для запроса 12e2db113ff929b0
- Установить, при каких конкретных значениях параметров ($1, $4 и др.) планировщик выбирает Seq Scan, а при каких — Index Scan. Если Seq Scan появляется при типичных для рабочей нагрузки значениях — это доказывает влияние устаревшей статистики.
- Статус: Неизвестно — необходимы auto_explain логи с параметрами.
Проверка состояния статистики для _InfoRg12488
- ❌Сравнить last_analyze, n_mod_since_analyze, last_autoanalyze между периодами. Если в P2 накоплено много изменений без актуального анализа — гипотеза подтверждается.❌(Невозможно)
- Статус: Неизвестно — данные pg_stat_user_tables отсутствуют.
Контролируемый эксперимент с online_analyze = on
- Повторить часовой интервал с единственным изменением — включить online_analyze (при прочих настройках P2). Снижение shared_blks_read и исчезновение Seq Scan для _InfoRg12488 станет прямым доказательством.
- Статус: Неизвестно — требуется тестовая среда.
Оценка влияния auto_explain
- Изменить auto_explain.log_min_duration на 1000 мс или отключить модуль, сохранив online_analyze = off. Измерить Total time и I/O time — это позволит количественно отделить накладные расходы логирования от эффекта смены планов.
- Статус: Неизвестно — требуется эксперимент.
Анализ wait events
- Если профиль ожиданий P2 насыщен DataFileRead при высокой утилизации диска, а WALWrite не доминирует — это согласуется с гипотезой.
- Статус: Неизвестно — данные ожиданий не предоставлены.
Ограничения текущего анализа (Неизвестно)
- Планы лишь для подмножества top‑SQL по времени выполнения; запросы‑лидеры по чтению могут не входить в эту выборку.
- Невозможно сопоставить частоту использования каждого варианта плана в P2 и их вклад в суммарные чтения.
- Размеры таблиц и их рост между периодами неизвестны.
- Семантика write_page_cost не прояснена.
ℹ️Вывод: гипотеза о локальной деградации планов из‑за устаревания статистики остаётся наиболее вероятной, но для окончательного подтверждения необходимы перечисленные выше данные.ℹ️
ℹ️Уточнение гипотезы с учётом информации о параметре write_page_cost
Общий технический итог
Сопоставление двух идентичных по длительности часовых интервалов (версия 15:2026-04-10, версия 17:2026-04-24) показало, что неизменные ключевые параметры кэширования и стоимостные константы (shared_buffers, effective_cache_size, work_mem, random_page_cost, seq_page_cost) исключают версию о переконфигурировании пула буферов. Основные изменения, зафиксированные в версии 17: отключение online_analyze.enable, активация auto_explain с логированием всех запросов, увеличение кэша планов и буферов WAL, а также установка параметра write_page_cost = 5. При этом абсолютный объём физических чтений вырос в 2,67 раза, доля времени I/O в общем времени выполнения — с 15,2 % до 62,0 %, а query‑level hit ratio снизился на 11,7 процентных пункта. Анализ планов для сопоставимых запросов выявил по крайней мере один случай (запрос к таблице _InfoRg12488), где в версии 17 появился план с последовательным сканированием, отсутствовавший в версии 15. Совокупность данных позволяет сделать вывод: наиболее вероятная причина ухудшения — работа планировщика на устаревшей статистике из-за отключения автоматического обновления статистики при DML и многократных сбросов кэша статистики (79 сбросов), что привело к ошибочному выбору Seq Scan для отдельных ресурсоёмких запросов. Фоновая нагрузка от auto_explain вносит дополнительный вклад в общее время выполнения, но не является первичным драйвером роста физических чтений.
Послесловие
ℹ️Приведённые выводы имеют статус обоснованной гипотезы, а не окончательной истины. Полное подтверждение требует получения дополнительных данных, которые не были доступны в рамках исходного анализа: планы и параметры вызова для запросов-лидеров по физическим чтениям, актуальность статистики по таблицам (pg_stat_user_tables), профиль событий ожидания (wait events), динамика роста объёмов данных, а также результаты контролируемых экспериментов с обратным включением online_analyze или отключением auto_explain. Без этих данных сохраняется риск смешения причин и следствий. Тем не менее, представленная методика сравнения конфигурации, метрик нагрузки и планов выполнения может служить типовым шаблоном для диагностики подобных аномалий при миграциях PostgreSQL.