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

Upgrade PostgreSQL 15→17: как отключение online_analyze и сбросы статистики обрушили кэш-хит и породили Seq Scan

Сравнительный анализ двух часовых интервалов: неизменные shared_buffers и стоимость планов, но падение query‑level hit ratio с 93,5 % до 81,8 %, рост физических чтений в 2,7 раза и появление Seq Scan для ресурсоёмких запросов.
Max: PG_EXPECTO
GitHub - Комплекс pg_expecto для статистического анализа производительности и нагрузочного тестирования СУБД
Оглавление

Сравнительный анализ двух часовых интервалов: неизменные shared_buffers и стоимость планов, но падение query‑level hit ratio с 93,5 % до 81,8 %, рост физических чтений в 2,7 раза и появление Seq Scan для ресурсоёмких запросов.

Postgres 17 быстрее? Не в этот раз
Postgres 17 быстрее? Не в этот раз

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.

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

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

-2

Предисловие

Миграция СУБД PostgreSQL на более новую версию часто ассоциируется с ожиданием повышения производительности или, как минимум, сохранения достигнутого уровня эффективности. Однако представленный в работе кейс демонстрирует противоположную ситуацию: после перехода с PostgreSQL 15 на 17 при идентичной пользовательской нагрузке (изменение числа запросов менее 1 %) наблюдается трёхкратное увеличение среднего времени выполнения запроса и многократный рост операций ввода-вывода. В статье приведены результаты сравнительного анализа конфигурационных параметров, агрегированных метрик нагрузки и планов выполнения запросов для двух часовых интервалов на версиях 15 и 17. Цель анализа — выявить наиболее вероятные причины деградации и предложить способы их подтверждения или опровержения.

Задача

  1. Выполнить сравнительный анализ конфигурации и производительности СУБД по данным раздела отчета pgpro_per "Top SQL by elapsed time (SQL-запросы с наибольшей длительностью)".
  2. Сформулировать и уточнить гипотезу о причинах проблем производительности СУБД после обновления версии СУБД с 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
-3

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) или аварийные перезапуски. Сами по себе обнуляют накопленные счётчики и обесценивают статистику планировщика.

-4

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.⬅️

-5

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

-6

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

Сопоставление двух идентичных по длительности часовых интервалов (версия 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.