Нейросеть рисует и пишет
20 постов
20 постов
16 постов
112 постов
40 постов
212 постов
114 постов
21 пост
В силу ограниченности платформы Пикабу - статья сокращена. Полностью - на основном канале Дзен.
PG_EXPECTO — это не просто инструмент, а целостный комплекс, построенный на двух новых принципах.
1. Комплексный статистический анализ (CSSA)
Система больше не разделяет метрики СУБД и инфраструктуры. Она создаёт единый корреляционный снимок всей системы:
Вертикальная корреляция: Вместо отдельных событий система видит цепочки: например, как медленный запрос вызывает рост очереди дисковых операций (iowait).
Проактивность: Комплекс отслеживает не сбои, а тренды. Он может предупредить: «Обнаружена устойчивая тенденция к деградации из-за X», позволяя устранить проблему до того, как она затронет пользователей.
2. Семантический анализ и нейросеть-ассистент
Это и есть та самая «турбина». Вместо сырых графиков PG_EXPECTO использует нейросеть, которая интерпретирует данные в контексте.
1. Производительность и ожидания СУБД
2. Метрика vmstat
3.Метрика iostat для дискового устройства, файловой системы /data
3.Метрика iostat для дискового устройства, файловой системы /wal
Проведи анализ производительности и ожиданий СУБД PostgreSQL за заданный период
На основе предоставленных данных можно провести следующий анализ производительности и ожиданий СУБД PostgreSQL за период с 08:40 до 09:40:
· Операционная скорость (SPEED):
o Коэффициент детерминации R2=0.88R2=0.88 → модель хорошо описывает данные.
o Угол наклона = -43.1 → скорость со временем снижается.
· Ожидания СУБД (WAITINGS):
o R2=0.75R2=0.75 → модель умеренно точна.
o Угол наклона = +40.87 → количество ожиданий растёт.
· SPEED vs WAITINGS: −0.763→ сильная отрицательная корреляция. Чем больше ожиданий, тем ниже скорость.
· WAITINGS vs IPC: 0.9039 → очень сильная положительная корреляция. Рост межпроцессного взаимодействия связан с ростом ожиданий.
· WAITINGS vs LWLOCK: 0.9587 → почти прямая зависимость. Ожидания сильно связаны с лёгкими блокировками (lightweight locks).
· SPEED:
o Начало: ~130 572
o Конец: ~90 948
o Снижение на ~30% за час.
· WAITINGS:
o Начало: 345
o Конец: 435
o Рост на ~26%.
· IPC и LWLOCK также растут, особенно заметно после 09:30.
1. Рост LWLOCK → возможна конкуренция за лёгкие блокировки (например, в памяти).
2. Рост IPC → увеличивается нагрузка на межпроцессное взаимодействие, возможно из-за параллельных запросов.
3. Падение SPEED при росте WAITINGS → система тратит больше времени на ожидания (возможно, из-за блокировок или нехватки ресурсов).
Проведи анализ метрик vmstat за заданный период
На основе данных vmstat за период с 08:40 до 09:40 проведён анализ производительности системы, на которой работает PostgreSQL. Вот ключевые выводы:
· Время простоя CPU (idle) снизилось с 90% до 85%.
· Пользовательская нагрузка CPU (us) выросла с 9% до 13%.
· Системная нагрузка CPU (sy) стабильна (2%).
· Ожиданий ввода-вывода (wa) не наблюдается (0%).
Показатель Начало Конец Изменение Комментарий
swpd 710МБ 749МБ +39 МБ Незначительный рост свопа, система не испытывает нехватки RAM.
free 7185МБ 3221МБ -3964 МБ Сильное снижение свободной памяти, что говорит о её активном использовании.
cache 53521МБ 55937МБ +2416МБ Кэш памяти увеличивается, что нормально при активной работе с диском.
Вывод: Память активно используется, но свопинг минимален — система работает в рамках доступной памяти.
Показатель Начало Конец Пиковое значение Тренд
bi (блоков ввода/с) 572 2409 2409 Резкий рост после 09:25.
bo (блоков вывода/с) 850 511 850 Снижение, затем стабилизация.
Вывод:
· После 09:25 резко выросла активность чтения с диска (bi).
· Это совпадает с падением SPEED в данных PostgreSQL.
· Возможно, это связано с увеличением количества запросов к данным, не помещающихся в кэш.
Показатель Начало Конец Изменение
in (прерываний/с) 12833 14503 +13%
cs (переключений контекста/с) 6835 7033 +3%
Вывод: Умеренный рост прерываний и переключений контекста, что соответствует увеличению нагрузки.
Сравнивая с предыдущим анализом cluster.txt, наблюдаем:
1. Рост ожиданий (WAITINGS) в PostgreSQL коррелирует с:
o Ростом bi (чтение с диска).
o Увеличением us (пользовательская нагрузка CPU).
2. Падение SPEED совпадает с:
o Увеличением bi (дисковые операции).
o Снижением idle CPU.
1. Дисковый ввод-вывод: резкий рост bi после 09:25 может быть причиной замедления.
2. Использование памяти: свободная память уменьшается, но свопинг незначителен — пока критично.
3. Нагрузка на CPU: idle снижается, но не до критических значений.
1. Оптимизация запросов:
o Увеличить shared_buffers, чтобы больше данных кэшировалось в памяти.
o Проверить наличие медленных запросов, выполняющих полное сканирование таблиц.
2. Мониторинг диска:
o Проверить скорость дисковых операций (например, с помощью iostat).
o Рассмотреть использование SSD или увеличение скорости дискового массива.
3. Настройка PostgreSQL:
o Увеличить effective_cache_size.
o Настроить work_mem для уменьшения операций на диске.
4. Системные настройки:
o Убедиться, что достаточно оперативной памяти для кэширования.
o Рассмотреть увеличение количества CPU, если нагрузка продолжит расти.
· График SPEED и bi на одной оси времени → проверить корреляцию.
· График WAITINGS и us (пользовательская нагрузка CPU).
· График free memory и cache → отследить использование памяти.
Отрицательная корреляция: Рост значений bi сопровождается снижением операционной скорости.
Положительная корреляция: Рост значений us сопровождается увеличением количества ожиданий.
Отрицательная корреляция: Рост значений free сопровождается снижением значений cache.
free -3964 МБ: Сильное снижение свободной памяти, что говорит о её активном использовании.
cache +2416 МБ: Кэш памяти увеличивается, что нормально при активной работе с диском.
На основе данных iostat для устройства vdb за период с 08:40 до 09:40 проведён анализ дисковых операций. Вот ключевые выводы:
· Устройство vdb используется для операций чтения и записи.
· %util (загрузка диска) выросла с 5.59% до 6.7% — загрузка низкая.
· aqu_sz (средняя длина очереди) незначительно снизилась с 0.26 до 0.20 — очереди практически нет.
Показатель Начало Конец Изменение Комментарий
r/s (чтений/с) 40.00 27.92 -30% Снижение количества операций чтения.
rMB/s (МБ/с) 0.84 2.82 +235% Резкий рост объёма читаемых данных.
rareq_sz (средний размер запроса) 19.35 КБ 67.09 КБ +247% Запросы стали крупнее.
r_await (среднее время чтения, мс) 2.07 3.73 +80% Увеличение времени отклика на чтение.
Вывод:
После 09:20 резко вырос объём читаемых данных (rMB/s) и средний размер запроса (rareq_sz). Это говорит о переходе на более крупные блоки данных, возможно из-за изменения типа запросов (например, сканирование больших таблиц).
Показатель Начало Конец Изменение
w/s (записей/с) 16.83 15.20 -10%
wMB/s (МБ/с) 0.62 0.26 -58%
wareq_sz (средний размер записи) 31.74КБ 4.22КБ -87%
w_await (среднее время записи, мс) 5.57 3.59 -36%
Вывод:
Нагрузка на запись снижается, операции становятся мельче и быстрее.
· После 09:20 наблюдается рост r_await (время чтения) и WAITINGS (ожидания в СУБД).
· Рост rMB/s совпадает с ростом WAITINGS и падением SPEED.
· Это подтверждает гипотезу о том, что увеличение времени доступа к диску влияет на производительность БД.
1. Увеличение времени чтения (r_await): с 2 мс до 3.7 мс — рост на 80%.
2. Увеличение размера запросов (rareq_sz): с 19 КБ до 67 КБ — возможно, из-за отсутствия индексов или полного сканирования таблиц.
3. Рост объёма читаемых данных (rMB/s): в 3 раза — нагрузка на диск возросла.
1. Оптимизация запросов PostgreSQL:
o Проверить выполнение планов запросов (EXPLAIN ANALYZE).
o Добавить индексы для часто сканируемых таблиц.
o Увеличить shared_buffers, чтобы больше данных кэшировалось в памяти.
2. Мониторинг диска:
o Проверить скорость диска (например, с помощью hdparm или fio).
o Убедиться, что диск не фрагментирован.
3. Настройка PostgreSQL:
o Увеличить effective_cache_size.
o Настроить random_page_cost и seq_page_cost в соответствии с типом диска.
4. Аппаратные улучшения:
o Рассмотреть переход на SSD, если используется HDD.
o Увеличить скорость дисковой подсистемы (RAID, кэширование).
· График rMB/s и WAITINGS на одной оси времени.
· График r_await и rareq_sz.
· График %util и aqu_sz для оценки загрузки диска.
Увеличение rMB/s сопровождается ростом количества ожиданий.
Основная причина деградации производительности — рост размера и времени выполнения дисковых операций чтения, что приводит к увеличению лёгких блокировок (LWLOCK) и ожиданий (WAITINGS) в СУБД.
1. Оптимизация запросов и индексов
2. Настройка параметров PostgreSQL (память, I/O)
3. Аппаратное улучшение дисковых подсистем
4. Мониторинг и алертинг ключевых метрик
Система не испытывает критической нехватки CPU или памяти, но дисковый ввод-вывод стал узким местом из-за изменившегося характера нагрузки (крупные запросы на чтение).
Взято с основного технического канала Postgres DBA (возможны правки в исходной статье).
При настройке PostgreSQL многие администраторы ориентируются на простое правило: «чем выше лимит соединений, тем больше соединений я могу обслужить». Казалось бы, установка max_connections = 1000 — это дальновидный запас на будущее. ⚠️Однако за этим решением скрывается неочевидная плата, которую база данных взимает ежесекундно, даже если большую часть времени вы используете лишь 20 подключений.
Вопреки распространенному мнению, проблема не сводится к «резервированию лишней памяти». В этом материале мы разберем, как статический размер структур ядра (массивы PGPROC, хеш-таблицы блокировок) влияет на алгоритмы планировщика, приводит к деградации кэша процессора и создает фоновую конкуренцию за спинлоки, поэтому работа с расчетом на «толпу» из 1000 процессов замедляет даже простые транзакции и это связано с устройством shared memory.
⚠️При установке `max_connections = 1000` PostgreSQL не выделяет всю память сразу под все 1000 соединений при старте, ‼️но ‼️резервирует системные структуры и ограничения, которые приводят к косвенному увеличению потребления памяти и ресурсов.
При запуске сервера PostgreSQL выделяет:
🔴max_connections — количество слотов для подключений (внутренние структуры `Backend` и `ProcArray`).
🔴max_prepared_transactions— если включены подготовленные транзакции.
🔴max_locks_per_transaction— количество блокировок на транзакцию (умножается на `max_connections` для расчёта общего лимита блокировок).
ℹ️Эти структуры выделяются в shared memory и не освобождаются в течение работы сервера. Их размер зависит от `max_connections` и других параметров.
ℹ️Не резервируется— 1000 × `work_mem` в оперативной памяти.
⚠️Резервируется— ‼️фиксированные структуры в shared memory‼️ (блокировки, слоты процессов, массивы транзакций).
⚠️Резервируется— системные лимиты(дескрипторы, память под метаданные).
ℹ️Резервирование памяти под неиспользуемые структуры — это только верхушка айсберга.
⚠️Главная проблема заключается в том, что даже в простое (при 20 активных соединениях из 1000 возможных) алгоритмы внутри PostgreSQL вынуждены работать с расчетом на "толпу" из 1000 конкурирующих процессов. Это создает постоянную фоновую нагрузку на механизмы синхронизации и планировщик.
Ниже приведено подробное описание того, как каждая структура влияет на производительность.
ℹ️Этот массив — один из главных источников косвенных издержек (overhead). Он представляет собой список структур, где каждый потенциальный backend (процесс обслуживания соединения) имеет свой слот.
🔴Влияние на планировщик и очереди ожидания: Ядро PostgreSQL и операционная система используют эти структуры для управления видимостью процессов и очередями. Когда активны только 20 процессов, но массив рассчитан на 1000, многие внутренние алгоритмы (например, поиск следующего процесса для получения блокировки или пробуждения) могут просматривать или учитывать "пустые" слоты. Хотя алгоритмы оптимизированы, сам размер управляющих структур влияет на скорость работы хеш-функций и поиска.
🔴Кэш-промахи (CPU Cache Misses): Это наиболее осязаемое влияние. Процессорный кэш (L1/L2/L3) — это очень быстрая, но маленькая память.
‼️Когда структура PGPROC массива раздута до 1000 элементов, она занимает значительно больше места. Даже если активны только 20 процессов, их рабочие структуры данных "размазаны" по большому участку памяти.
Это снижает вероятность того, что данные текущего активного процесса находятся в быстром кэше процессора (Cache Locality), увеличивая количество обращений к медленной оперативной памяти.
⚠️Это наиболее критичная часть с точки зрения алгоритмической сложности. Эти таблицы представляют собой хеш-таблицы в разделяемой памяти.
🔴Деградация хеш-таблиц (Hash Table Degradation):
ℹ️ Размер этих таблиц изначально рассчитывается исходя из max_connections * max_locks_per_transaction . Это значение используется как max_size при создании хеш-таблицы.
⚠️Проблема: Если фактическое количество блокировок (занятых записей в таблице) значительно меньше расчетного max_size, это не страшно. Но если вы выставили max_size под 1000 соединений, а используете 20, внутренняя структура таблицы (количество "корзин" — buckets) рассчитывается под это большое значение .
ℹ️Механизм замедления: При добавлении новой блокировки (а это происходит постоянно при работе даже 20 соединений) хеш-функция вычисляет индекс "корзины". Из-за того, что корзин много, они могут быть почти пустыми, но сам процесс вычисления хеша и перехода по ссылкам происходит в контексте большой таблицы. В сценариях, где таблица блокировок почти пуста (как в нашем случае с 20 соединениями), замедление минимально, но оно есть. ⚠️Главная опасность возникает, когда количество блокировок начинает расти — производительность такой таблицы падает нелинейно.
ℹ️Комментарий в исходном коде: Разработчики PostgreSQL прямо комментируют это в функции ShmemInitHash: эффективность доступа (access efficiency) будет деградировать, если размер таблицы существенно превышен, так как это влияет на размер директории и переполнение корзин (buckets get overfull) .
🔴Конкуренция за спинлоки (Spinlock Contention): Даже если блокировок немного, сам механизм доступа к глобальным структурам данных (разделяемым хеш-таблицам) требует захвата легковесных блокировок (LW Locks) или спинлоков. Когда эти таблицы имеют большой размер, управление ими требует более сложной синхронизации, что увеличивает шансы на то, что два процесса одновременно попытаются обратиться к разным частям одной большой структуры, вызывая микро-задержки .
ℹ️Сюда входят различные слоты: идентификаторы транзакций (XID), идентификаторы команд (Command ID) и другие глобальные счетчики.
🔴Влияние на инфраструктуру ожидания (LWLock и семафоры):
Процессы часто ждут сигналов о завершении действий других процессов (например, записи в WAL). Инфраструктура для этих ожиданий (LWLock Wait and Wake) также завязана на количество потенциальных участников .
ℹ️Пример с WAL (журнал предзаписи): Когда 20 процессов пытаются одновременно записать изменения, они конкурируют за WALInsertLock. Механизмы, управляющие этим (например, NUM_XLOGINSERT_LOCKS), эвристически подбираются под MaxConnections . Если MaxConnections огромен (1000), механизмы синхронизации WAL могут использовать более "тяжелые" алгоритмы, ожидая высокой конкуренции, что добавляет лишние циклы CPU даже при низкой конкуренции.
🔴Пробуждение процессов: Система должна отслеживать, кого разбудить при снятии блокировки или завершении записи. ⚠️Чем больше max_connections, тем сложнее структуры данных, которые необходимо обойти для принятия решения о пробуждении (даже если спит всего 1 процесс).
Разбирая внутренности PostgreSQL, мы столкнулись с удивительным парадоксом: иногда «запас» работает против вас. Массив PGPROC, рассчитанный на тысячу процессов, превращает быстрый процессорный кэш в захламленный склад, а хеш-таблицы блокировок, настроенные на толпу, даже в моменты простоя вынуждают ядро использовать более тяжелые алгоритмы синхронизации.
ℹ️Это тот случай, когда невидимый глазу оверхед накапливается снежным комом. Система тратит такты не на обработку ваших данных, а на управление потенциальной, но несуществующей нагрузкой. Поэтому, настраивая PostgreSQL, стоит помнить: щедрость в отношении лимитов соединений оборачивается скупостью производительности. Оптимальная стратегия — держать max_connections на уровне разумного минимума, достаточного для работы пулера соединений и выполнения фоновых задач, чтобы ядро базы данных не «отвлекалось» на обслуживание фантомных процессов.
Взято с основного технического канала Postgres DBA (возможны правки в исходной статье).
Традиционный подход к диагностике производительности PostgreSQL зачастую опирается на эвристики, «типовые чек‑листы» и интуицию администратора. Администратор видит всплеск ожиданий, находит самый массовый тип события и принимает решение: «увеличить shared_buffers» или «выключить параллельные запросы». Такой метод работает в очевидных случаях, но оказывается бессилен, когда система находится в состоянии сложного баланса между разными механизмами, а первопричина торможения скрыта за вторичными эффектами.
Статистический подход, реализованный в методике pg_expecto, принципиально меняет логику расследования. Вместо субъективного выбора «самого громкого» типа ожиданий во главу угла ставятся количественные критерии, основанные на реальном поведении системы во времени.
Применение корреляционного и регрессионного анализа позволяет решить три критически важные задачи:
Отсечь иллюзорные связи. Тип ожидания может быть многочисленным, но при этом не оказывать системного влияния на рост общей задержки. Статистическая значимость (p‑value) и низкая взвешенная корреляция (ВКО)отфильтровывают такие события, экономя часы бесполезных настроек.
Выявить скрытые доминанты. Нередко тип ожидания, занимающий лишь 10–15% в структуре событий, на поверку оказывается «бутылочным горлышком», с которым жёстко связан общий рост ожиданий. Именно его корректировка даёт максимальный прирост производительности. ВКО как интегральная метрика ранжирует проблемы именно по степени их фактического влияния на нагрузку, а не по частоте появления в логах.
Оценить предсказуемость и устойчивость. Высокий коэффициент детерминации (R²) регрессионной модели говорит о том, что связь между типом ожидания и общей задержкой стабильна и воспроизводима. Это не разовый выброс, а системный паттерн. Низкий R², напротив, предупреждает: даже значимый по корреляции тип ожидания ведёт себя хаотично, и его оптимизация может дать непредсказуемый результат.
В практическом примере, представленном в статье , именно статистический анализ позволил объективно выделить IPC как доминирующий фактор (ВКО = 0,74) и обосновать первоочередность его настройки, несмотря на то что в «сырых» счётчиках событий он мог не бросаться в глаза. Одновременно были отсеяны типы, которые при поверхностном взгляде часто вызывают неоправданное беспокойство (например, Lock или BufferPin).
Таким образом, внедрение статистических методов превращает анализ производительности из искусства субъективных догадок в инженерную дисциплину, опирающуюся на объективные метрики и воспроизводимые выводы. Представленный отчёт — наглядная демонстрация того, как точные расчёты помогают принимать решения об оптимизации с предсказуемым положительным эффектом.
Методика предназначена для количественной оценки производительности PostgreSQL, выявления узких мест и факторов, вызывающих задержки, на основе статистического анализа временных рядов событий ожидания(wait_event_type). Применяется при нагрузочном тестировании, мониторинге продуктивных систем или постмортем‑анализе инцидентов.
Данная методика позволяет системно подойти к выявлению причин замедления PostgreSQL, опираясь исключительно на статистические свойства собранных метрик, и даёт чёткие критерии для принятия решений об оптимизации.
Для анализа необходимы:
временные ряды операционной скорости ;
временные ряды суммарного количества ожиданий СУБД ;
временные ряды событий ожидания по типам (wait_event_type): BufferPin, Extension, IO, IPC, Lock, LWLock, Timeout .
Шаг 1. Оценка корреляции с суммарными ожиданиями
Вычисляется коэффициент корреляции Пирсона между суммарными количествами ожиданий СУБД и событиями ожидания конкретного типа .
Проверка значимости:
Если p‑value ≥ 0,05 – тип исключается из дальнейшего анализа (связь нестабильна).
Если значимо – переходим к шагу 2.
Шаг 2. Расчёт взвешенной корреляции ожиданий (ВКО)
ВКО – интегральная метрика, ранжирующая типы ожиданий по степени их влияния на нагрузку. Значение ВКО лежит в пределах [0,1].
Порог отбрасывания: ВКО < 0,01 – влияние пренебрежимо мало, тип игнорируется.
Чем выше ВКО, тем критичнее проблема. Значения, близкие к 1, требуют немедленного анализа.
Шаг 3. Построение регрессионной модели
Для типов ожиданий, прошедших шаги 1 и 2, строится линейная регрессия вида:
Y = a + b·X,
где Y – суммарные ожидания, X – ожидания данного типа.
Оценивается R² модели .
R² ≥ 0,8 — исключительно сильная модель, прогноз надёжен.
0,6 ≤ R² < 0,8 — качественная модель.
0,4 ≤ R² < 0,6 — приемлемая модель.
0,2 ≤ R² < 0,4 — слабая модель.
R² < 0,2 — модель непригодна для прогнозирования.
Дата тестирования: 2026-02-12 (14:11 – 16:00)
Объект: PostgreSQL (нагрузочное тестирование)
Операционная скорость: демонстрирует умеренный рост (угол наклона +38,6).
Качество модели: хорошее (R² = 0,64). Достоверный, практически полезный тренд.
Общие ожидания СУБД: растут опережающими темпами (угол наклона +43,3).
Качество модели: очень высокое (R² = 0,89). Прогнозная способность высокая, связь сильная.
Взаимосвязь скорости и ожиданий:
Коэффициент детерминации R² = 0,69 — качественная модель.
Рост ожиданий сопровождается ростом операционной скорости (положительная корреляция).
Вывод: увеличение нагрузки приводит к соразмерному росту как производительности, так и времени ожидания. Система работает на пределе эффективности, требуется анализ узких мест.
Критерии отбора:
Статистическая значимость корреляции (p < 0,05).
Взвешенная корреляция ожиданий (ВКО) ≥ 0,01.
Коэффициент детерминации R² ≥ 0,2.
Отсеяны (не влияют или некоррелируют):
BufferPin, Extension, Lock — отрицательная/отсутствующая корреляция, дальнейший анализ не требуется.
Тип ожидания: IPC (межпроцессное взаимодействие)
ВКО = 0,74 — критическое значение. Основной фокус расследования.
Корреляция с общими ожиданиями: очень сильная (R = 0,981, R² = 0,96).
Модель регрессии: R² = 0,96 — исключительно сильная, прогноз исключительно точный.
Рекомендации:
Настройка параллельных запросов (max_parallel_workers_per_gather, max_parallel_workers).
Оптимизация фоновых процессов (autovacuum, background writer, checkpointer).
Увеличение shared_buffers для снижения конкуренции.
Возможно выделение отдельного инстанса под тяжёлые аналитические запросы.
Тип ожидания: IO (ввод-вывод)
ВКО = 0,18 — высокое значение.
Корреляция: сильная (R = 0,867, R² = 0,75). Модель качественная.
Рекомендации:
Агрессивная настройка autovacuum для горячих таблиц (снижение порогов, частая очистка).
Разделение таблиц и индексов по разным табличным пространствам на отдельных дисках.
Миграция наиболее интенсивно используемых данных на быстрые накопители (NVMe/SSD).
Тип ожидания: LWLock
ВКО = 0,01 — низкое, статистически значимая корреляция (R = 0,902, R² = 0,81).
Влияние на общую нагрузку минимально, но модель очень сильная.
Рекомендации (при ухудшении):
Обновление PostgreSQL до версий с улучшенными алгоритмами LWLock.
Выделение специализированных инстансов для разных типов нагрузки.
Консультация с экспертами по тонкой настройке.
Тип ожидания: Timeout
ВКО = 0,01 — низкое, корреляция очень сильная (R = 0,979, R² = 0,96).
Текущее влияние незначительно, но высокая предсказуемость.
Рекомендации (при ухудшении):
Реорганизация длинных транзакций, уменьшение их количества.
Внедрение механизмов повторных попыток с экспоненциальной задержкой на стороне приложения.
Обучение разработчиков работе с асинхронными вызовами.
Система работает под высокой нагрузкой, что подтверждается устойчивым ростом как производительности, так и времени ожидания. Тренд ожиданий усиливается быстрее — потенциальный риск деградации при дальнейшем росте нагрузки.
Основной источник проблем — IPC (74% взвешенного влияния). Необходима срочная диагностика и оптимизация механизмов параллелизма и фоновых процессов.
Второй значимый фактор — подсистема ввода-вывода (18% влияния). Требует плановой оптимизации с акцентом на физическое размещение данных и настройку autovacuum.
Остальные типы ожиданий (LWLock, Timeout) в настоящее время не создают критических задержек, но их высокие корреляции сигнализируют о наличии потенциально опасных паттернов. Рекомендуется мониторинг и превентивные архитектурные улучшения.
Типы BufferPin, Extension, Lock не оказывают значимого влияния — фокусироваться на них нецелесообразно.
IPC
Проверить текущие значения max_parallel_workers_per_gather, max_parallel_workers, max_worker_processes.
Оценить загрузку autovacuum и background writer, настроить их интенсивность.
Рассмотреть увеличение shared_buffers (при достаточном ОЗУ).
IO
Выявить наиболее «горячие» таблицы и индексы.
Настроить пороги autovacuum (autovacuum_vacuum_scale_factor, autovacuum_vacuum_threshold).
При наличии нескольких физических дисков — распределить табличные пространства.
Мониторинг
Установить длительный сбор статистики по ожиданиям IPC и IO.
Отслеживать динамику ВКО по LWLock и Timeout.
Отчет составлен на основе статистического анализа с применением взвешенной корреляции ожиданий (ВКО), регрессионного анализа и проверки значимости связей.
Представленная методика комплексного статистического анализа ожиданий PostgreSQL (реализованная в комплексе pg_expecto) знаменует принципиальный сдвиг в подходе к диагностике производительности СУБД.
Новизна исследования заключается не в самом факте сбора событий ожидания — это давно доступно, — а в переходе от плоскостного ранжирования по частоте к многомерной статистической оценке.
Влияние типа ожидания оценивается не изолированно, а в системной связке с общей динамикой задержек;
Введена интегральная метрика ВКО (взвешенная корреляция ожиданий), позволяющая объективно ранжировать проблемы по степени их фактического воздействия на нагрузку;
Применён жёсткий статистический фильтр, отсекающий случайные и нестабильные корреляции;
Качество каждой выявленной связи верифицируется через коэффициент детерминации (R²), что даёт уверенность в воспроизводимости результата.
Практическая ценность методики уже подтверждена в ходе нагрузочного тестирования:
Второстепенные и шумовые типы ожиданий (BufferPin, Extension, Lock) отброшены автоматически — без затрат времени на их анализ;
Скрытый доминант — IPC — выявлен и обоснован как первоочередная цель оптимизации (ВКО = 0,74), хотя в структуре событий он мог не быть самым массовым;
По каждому значимому типу сформулированы конкретные, применимые немедленно рекомендации и контрольный чек-лист.
Таким образом, pg_expecto превращает трудно формализуемое искусство «тонкой настройки PostgreSQL» в воспроизводимый инженерный процесс, где каждое решение опирается на математически обоснованные критерии, а эффект оптимизации становится предсказуемым.
Предложенный подход не заменяет экспертизу администратора, но вооружает её точными инструментами измерения, позволяя фокусировать усилия именно там, где они принесут максимальный результат. Это первый шаг к созданию полноценной предиктивной аналитики производительности PostgreSQL, и уже сегодня он готов к промышленному применению.
Взято с основного технического канала Postgres DBA (возможны правки в исходной статье).
В мире администрирования PostgreSQL данные об ожиданиях (wait events) являются ключевым источником диагностики производительности. Однако отдельные метрики без аналитической обработки создают лишь информационный шум, не отвечая на главный вопрос: какой тип ожиданий действительно определяет общую нагрузку на систему?
Метод «Взвешенной корреляции ожиданий (ВКО)», реализованный в комплексе PG_EXPECTO, основан на серьёзной теоретической базе. Он сочетает корреляционный анализ для оценки силы связи между типом ожиданий и общей нагрузкой с взвешиванием по значимости, учитывающим долю каждого типа. Без этого фундамента метрика оставалась бы просто числом, а не стратегическим инструментом приоритизации.
Именно теория превращает ВКО в точный компас, который позволяет отделить системные узкие места от фонового шума и сфокусироваться на главной причине проблем — будь то ожидания IO, IPC или блокировок.
В статье рассматривается , как теоретические принципы статистики воплощаются в практический инструмент для анализа производительности PostgreSQL, способный превращать данные в чёткий план действий.
Корреля́ция (от лат. correlatio «соотношение»), или корреляцио́нная зави́симость — статистическая взаимосвязь двух или более случайных величин (либо величин, которые можно с некоторой допустимой степенью точности считать таковыми), при этом изменения значений одной или нескольких из этих величин сопутствуют систематическому изменению значений другой или других величин.
Положительная корреляция в таких условиях — это такая связь, при которой увеличение одной переменной связано с увеличением другой переменной.
Score = Corr(WaitType, Total) * P(WaitType)
Corr ∈ [0, 1]: коэффициент корреляции между ожиданиями данного типа wait_event_type ∈ [BufferPin, Extension, IO, IPC, Lock, LWLock, Timeout] и всеми ожиданиями СУБД за выбранный период .
P ∈ [0, 1]: доля в процентах(деленная на 100) количества ожиданий данного типа wait_event_type ∈ [BufferPin, Extension, IO, IPC, Lock, LWLock, Timeout] ко всем ожиданиями СУБД за выбранный период .
"Взвешенная корреляция ожиданий (ВКО)" отвечает на вопрос: "Насколько данный тип ожиданий является доминирующим и стабильным фактором, определяющим общую нагрузку ожиданиями в системе?"
Проще говоря, она помогает ранжировать проблемы и отделить системные, хронические узкие места от всплесков или шума.
Ранг 5 (Критический) — Score ≥ 0.20
Что это значит: Явное, системное узкое место. Данный тип ожиданий является основным драйвером проблем производительности в системе. Высокая доля и сильная связь с общей нагрузкой.
Характер проблемы: Емкостное (ресурсное) ограничение или масштабная логическая проблема, затрагивающая всю СУБД.
Типовые мероприятия:
Немедленный детальный анализ этого конкретного типа ожиданий
Оценка загрузки соответствующего ресурса ОС (если это IO — дисковые утилизации и задержки; IPC/LWLock — загрузка CPU, межпроцессное взаимодействие).
Анализ топ-запросов по общему времени и времени ожиданий данного типа.
Приоритетная настройка/оптимизация: Для IO — настройка work_mem, effective_io_concurrency, проверка индексов; для Lock — анализ долгих транзакций, оптимизация логики приложения.
Рассмотрение вопросов масштабирования/апгрейда (более быстрые диски, увеличение RAM, добавление CPU ядер).
Ранг 4 (Высокий) — 0.10 ≤ Score < 0.20
Что это значит: Существенный фактор, влияющий на производительность. Проблема является заметной и устойчивой, но может быть не единственной.
Характер проблемы: Локальное емкостное ограничение или широко распространенная логическая проблема.
Типовые мероприятия:
Целевой анализ запросов, создающих данный тип ожиданий.
Проверка конфигурации СУБД, связанной с этой областью (shared_buffers, max_connections, настройки блокировок и т.д.).
Глубокий мониторинг этого типа ожиданий во времени для выявления пиков и их триггеров.
Планирование оптимизационных работ (перестройка индексов, рефакторинг проблемных участков кода приложения, настройка пулеров соединений).
Рассмотрение точечных улучшений инфраструктуры.
Ранг 3 (Средний) — 0.04 ≤ Score < 0.10
Что это значит: Заметная проблема второго плана. Может быть либо важной, но редко проявляющейся, либо частой, но не являющейся основным ограничителем.
Характер проблемы: Периодические всплески или симптом более глубокой проблемы.
Типовые мероприятия:
Анализ в связке с другими метриками: Необходимо смотреть, не маскирует ли эта проблема другую (например, высокие LWLock могут быть следствием плохого плана запроса).
Сбор дополнительного контекста: В какое время суток проявляется? С какими конкретными операциями (SELECT, UPDATE, VACUUM) связан?
Оптимизация "низко висящих фруктов": Проверка очевидных вещей — достаточно ли maintenance_work_mem для AUTOVACUUM, нет ли явных дедлоков.
Включение в список для регулярного аудита, но без срочных действий.
Ранг 2 (Низкий) — 0.01 ≤ Score < 0.04
Что это значит: Фоновый шум или нишевая проблема. Не оказывает значительного влияния на общую производительность системы в текущий момент.
Характер проблемы: Узкая проблема, затрагивающая специфичные операции, или стабильный фоновый шум.
Типовые мероприятия:
Документирование и наблюдение. Зафиксировать факт наличия ожиданий данного типа.
Установка базового уровня (baseline). Это норма для данной системы?
Проверить, не является ли это симптомом неправильной настройки мониторинга или сбора статистики.
Действия требуются только в случае роста Score или появления связанных с этим алертов (например, таймауты приложений).
Ранг 1 (Минимальный) — 0 < Score < 0.01
Что это значит: Статистический шум. Вклад в общие проблемы производительности пренебрежимо мал.
Характер проблемы: Практически отсутствует.
Типовые мероприятия:
Игнорировать в рамках анализа производительности. Не тратить время на расследование.
Возможно, стоит проверить корректность вычисления метрик (достаточен ли объем выборки, нет ли ошибок в запросе).
Учесть как часть общей картины для полноты отчета, но без выделения отдельного внимания.
Ранжирование следует использовать как фильтр для приоритизации. Даже при среднем ранге (3) проблема может быть критичной для конкретной бизнес-операции.
Метрика «Взвешенная корреляция ожиданий (ВКО)», реализованная в комплексе PG_EXPECTO, представляет собой мощный инструмент для системного и объективного анализа производительности PostgreSQL. Её основная ценность заключается не просто в диагностике наличия ожиданий, а в расстановке приоритетов при устранении узких мест.
На практике администратор или разработчик часто сталкивается с десятками различных метрик и типов ожиданий, что может привести к «аналитическому параличу» — попыткам оптимизировать всё сразу без чёткого понимания, что влияет на систему больше всего. ВКО решает эту проблему, отвечая на ключевой вопрос: какой тип ожиданий является основным, стабильным драйвером проблем в данный период времени?
Использование системы рангов (от критического 5 до минимального 1) позволяет:
Мгновенно сфокусироваться на главном источнике проблем (Score ≥ 0.20), игнорируя статистический шум.
Планировать работы на основе данных: высокий и средний ранги указывают на целевые области для глубокого анализа конфигурации СУБД, оптимизации запросов или инфраструктуры.
Разделять системные, хронические проблемы от ситуационных всплесков, что критически важно для планирования долгосрочных улучшений и точечных «тушению пожаров».
Создавать объективную основу для отчётности, переходя от субъективных ощущений «система тормозит» к конкретным утверждениям: «доминирующим фактором нагрузки являются ожидания типа IO с весом 0.25».
Как показано в примере с имитацией OLAP-нагрузки, метрика наглядно выделяет доминирующие типы ожиданий (например, IO и IPC), предоставляя отправную точку для углублённого анализа: изучения топ-запросов, проверки дисковых подсистем или настройки параметров параллелизма.
Таким образом, ВКО — это не просто ещё один показатель, а стратегический фильтр и компас для специалистов по производительности. Она позволяет превратить разрозненные данные о событиях ожидания в чёткий план действий, экономя время и ресурсы и направляя усилия туда, где они дадут максимальный эффект для устойчивой и предсказуемой работы СУБД PostgreSQL.
Взято с основного технического канала Postgres DBA (возможны правки в исходной статье).
Тестирование производительности PostgreSQL часто упирается в вопрос: как система поведёт себя под реальной, смешанной нагрузкой? Методы «на глазок» и разрозненные метрики не дают полной картины. PG_EXPECTO v.6 — инструмент, который целенаправленно создаёт реалистичную имитацию OLTP и OLAP-нагрузки, дополняя её структурированными чек-листами по вводу-выводу и памяти, а также ключевой статистикой по vm_dirty и shared_buffers для глубокой диагностики.
# НАСТРОЙКИ НАГРУЗОЧНОГО ТЕСТИРОВАНИЯ
# 6.0
# Максимальная нагрузка
finish_load = 20
# Тестовая БД
testdb = default
# testdb = demo
# Тип синтетической нагрузки
load_mode = oltp
#load_mode = olap
# Веса сценариев по умолчанию
scenario1 = 0.7
scenario2 = 0.2
scenario3 = 0.1
# Инициализировать тестовую БД
init_test_db = on
#init_test_db = off
# Размер тестовой БД
# ~200MB
#scale = 20
#~10GB
scale = 685
Тип имитируемой нагрузки определяется значением параметра "load_mode":
oltp : Нагрузочное тестирование под синтетической нагрузкой, имитирующей OLTP.
olap : Нагрузочное тестирование под синтетической нагрузкой, имитирующей OLAP.
Исходный файл: postgres.1.1.shared_buffers.report.txt
Исходный файл: linux.5.1.vm_dirty.txt
Имитация нагрузки — это лишь первый шаг. Истинная ценность подхода, реализованного в PG_EXPECTO v.6, — в целостной интерпретации результатов. Когда данные с «датчиков» vm_dirty и shared_buffers рассматриваются через призму чек-листов по IO и RAM, вы перестаётся быть пассивным наблюдателем за сбоями. Вы становитесь инженером, который понимает язык своей системы и может проактивно устранять риски, обеспечивая её устойчивость и скорость. Добро пожаловать в эпоху осознанной производительности.
Эффективность параметров настройки CPU для PostgreSQL сильно зависит от типа нагрузки: OLTP требует минимальной задержки и эффективной обработки множества коротких операций, а OLAP — максимальной пропускной способности для сложных вычислений.
Основываясь на анализе практических тестов и рекомендаций, вот ключевые параметры, сгруппированные по категориям.
Управляющий драйвер (governor)
Для OLTP: performance. Фиксация на максимальной частоте снижает задержку каждой транзакции.
Для OLAP: performance или schedutil. Стабильно высокая частота или интеллектуальное управление от планировщика ядра ускоряют обработку объемных данных.
Состояния простоя (C-states)
Для OLTP: Ограничение глубоких состояний (например, processor.max_cstate=1). Снижает латентность при частых переходах от простоя к активности, что критично для отклика транзакций.
Для OLAP: Менее критично. Можно разрешить более глубокие состояния для энергосбережения, так как запросы длительные и массовые.
Планировщик задач ядра Linux
Для OLTP: Отключение sched_autogroup_enabled. Предотвращает несправедливое распределение CPU между фоновыми процессами СУБД (например, autovacuum) и обработкой запросов.
Общая рекомендация: Настройка sched_min_granularity_ns. Увеличение значения может снизить накладные расходы на переключение контекста при высокой конкуренции за CPU.
Параметры параллелизма PostgreSQL
Для OLAP: Крайне важны. Увеличение max_parallel_workers_per_gather, max_worker_processes. Позволяют одним аналитическим запросом задействовать несколько ядер, значительно ускоряя выполнение.
Для OLTP: Обычно не требуют изменений. Короткие транзакции редко используют параллельное выполнение.
Изоляция CPU (cgroups, systemd, isolcpus)
Для смешанных нагрузок (OLTP+OLAP): Выделение отдельных ядер для фоновых процессов PostgreSQL (autovacuum, WAL writer) или для выполнения аналитических запросов. Это предотвращает их вмешательство в обработку критичных транзакций.
Для чистого OLTP/OLAP: Менее актуально, но может использоваться для тонкой настройки под конкретную задачу.
Управление прерываниями (irqbalance, smp_affinity)
Для обеих нагрузок: Привязка сетевых прерываний и прерываний дисковой подсистемы к выделенным ядрам. Освобождает основные ядра для обработки запросов, улучшая предсказуемость производительности.
Политики NUMA (numactl, numa_balancing)
Для больших серверов: Отключение numa_balancing и ручная привязка экземпляра PostgreSQL к одному узлу NUMA. Уменьшает задержки при доступе к памяти, что важно для интенсивных нагрузок.
Производительность CPU тесно связана с корректной настройкой памяти и ввода-вывода в PostgreSQL.
Память: shared_buffers (25-40% RAM) и work_mem. Недостаток work_mem приводит к записи временных данных на медленный диск, что создает очередь процессов в состоянии D (b), висящую на iowait, и имитирует проблему с CPU.
Ввод-вывод: random_page_cost (понизить для SSD), effective_io_concurrency. Правильные настройки заставляют планировщик чаще выбирать индексные сканы, снижая нагрузку на CPU.
Определите профиль нагрузки с помощью мониторинга (например, pg_stat_statements).
Начните с настройки PostgreSQL, особенно параметров памяти и autovacuum.
Задайте CPU governor в performance — это безопасно и почти всегда дает положительный эффект.
Для OLAP-нагрузки активируйте и настройте параллельные запросы в PostgreSQL.
Если проблема сохраняется, используйте мониторинг (top, perf, vmstat) для выявления узких мест: высокой очереди (runqueue), iowait или переключений контекста. Только затем тонко настраивайте параметры ядра (C-states, планировщик).
Протестируйте каждое изменение на нерабочем стенде. Используйте нагрузочное тестирование, например, pgbench.
В целом, для OLTP ключевыми являются стабильно высокая частота CPU и минимизация латентности (governor, C-states). Для OLAP — максимальная пропускная способность параллельных вычислений (параметры параллелизма Postgres). Настройка параметров ОС (планировщик, изоляция) становится критичной на высоконагруженных системах или при смешанной нагрузке.
Параметры vm.dirty_background_bytes и vm.dirty_bytes работают в паре, устанавливая два порога. Первый активирует фоновую запись, а второй вызывает блокирующую запись, останавливающую процессы.
vm.dirty_background_bytes: максимальный объем «грязной» памяти в байтах, при достижении которого ядро начинает фоновую запись данных на диск.
vm.dirty_bytes: абсолютный лимит в байтах. При его достижении все процессы, генерирующие новые «грязные» данные, будут приостановлены до завершения записи.
Цели настройки:
Для интерактивных десктопов/серверов с латентностью: минимизировать задержки, установив низкие пороги для частой записи.
Для серверов с высокой пропускной способностью записи : установить высокие пороги, чтобы накапливать большие порции данных для эффективной записи.
Предотвращение внезапных блокировок I/O: dirty_bytes должен быть значительно больше dirty_background_bytes, чтобы у фоновых потоков было время на очистку.
ВАЖНО: dirty_background_bytes и dirty_background_ratio (а также dirty_bytes и dirty_ratio) являются взаимоисключающими парами. При установке значения в байтах соответствующий параметр в процентах автоматически обнуляется, и наоборот.
Перед настройкой необходимо собрать данные о системе и ее текущем состоянии.
1. Анализ текущих значений и конфигурации ОС:
Посмотреть актуальные значения параметров:
sysctl vm.dirty_background_bytes vm.dirty_bytes vm.dirty_background_ratio vm.dirty_ratio
Определить общий объем оперативной памяти (RAM):
grep MemTotal /proc/meminfo
Ключевые метрики:
wkB/s или MB_wrtn/s — скорость записи.
%util — загрузка устройства (близко к 100% указывает на насыщение).
await (в частности, w_await) — среднее время ожидания операции записи (высокое значение указывает на проблемы).
3. Оценка давления на память и ввод-вывод с помощью vmstat:
Ключевые метрики для диагностики проблем с dirty pages:
memory: swpd, free, buff, cache — если free мало, а cache велик, это может указывать на активное использование страниц.
swap: si, so — ненулевые значения могут указывать на нехватку памяти, влияющую на политику записи.
cpu: wa — высокий процент времени ожидания ввода-вывода (wa) часто коррелирует с блокировками процессов при достижении лимита dirty_bytes.
Шаг 1: Определение целевого времени сброса данных
Основная идея — связать объем данных со скоростью диска, чтобы контролировать максимальное время, за которое данные могут быть записаны.
Рекомендуется, чтобы фоновая запись (dirty_background_bytes) могла завершиться за 100-500 мс. Это предотвращает длительные блокировки при достижении верхнего лимита.
Для расчета используйте пиковую скорость записи (write_speed_mb_ps), полученную из iostat.
Шаг 2: Расчет vm.dirty_background_bytes
Формула:
vm.dirty_background_bytes = target_writeback_time_ms * write_speed_mb_ps * 1024 * 1024 / 1000
Пример для SSD (скорость ~200 МБ/с, целевое время 250 мс):
250 мс * 200 МБ/с * 1048576 / 1000 ≈ 52428800 байт (50 МБ)
Это значение можно округлить до 50-60 МБ.
Шаг 3: Расчет vm.dirty_bytes
Верхний лимит должен давать буфер поверх фонового порога.
Минимальный множитель: 2x от dirty_background_bytes.
Рекомендуемый диапазон: 4x-8x от dirty_background_bytes.
Формула:
vm.dirty_bytes = N * vm.dirty_background_bytes, где N от 4 до 8.
Пример (продолжение):
vm.dirty_bytes = 6 * 50 МБ = 300 МБ (314572800 байт)
Слишком низкие значения:
Симптомы: высокий %system и cs в vmstat, низкая общая пропускная способность записи.
Решение: увеличьте dirty_background_bytes (и, соответственно, dirty_bytes), чтобы позволить накапливаться большим пакетам данных.
Слишком высокие значения:
Симптомы: длительные пики wa в vmstat при всплесках записи, ощутимые «подвисания» системы.
Решение: уменьшите оба параметра, особенно dirty_background_bytes, чтобы активировать запись раньше.
Активное использование свопа (si/so > 0):
Проблема может быть не в dirty pages, а в общем дефиците памяти. Рассмотрите возможность увеличения RAM или настройки vm.swappiness.
В мире IT-мониторинга и DevOps сложился своеобразный культ метрик. Среди них «CPU Utilization» (загрузка процессора) долгое время занимала трон главного короля, чье малейшее движение к 100% вызывало панику и триггерило спасательные операции. Однако в современной, сложной и распределенной инфраструктуре слепая вера в эту метрику не просто устарела — она стала вредной. Высокая утилизация CPU сама по себе не является инцидентом; это лишь симптом, требующий не аварийного реагирования, а профессиональной диагностики. Непонимание этого проистекает из фундаментальных недостатков самой метрики и приводит к ложным выводам, тогда как фокус должен сместиться на анализ метрик производительности.
Само понятие «утилизации» в контексте современных процессоров крайне условно. Процессор — не линейный и не однородный ресурс, подобный оперативной памяти. Его работа включает разные состояния (idle, user, system, iowait, steal в Linux), разные ядра и технологии вроде Hyper-Threading. Метрика «средней утилизации за 1-5 минут» — это грубое усреднение, стирающее важнейшие детали.
· Контекст решает всё: 90% утилизации на веб-сервере, обрабатывающем пиковую нагрузку, — это признак здоровья и эффективного использования дорогого железа. Те же 90% на базе данных, выполняющей тяжелый аналитический запрос, могут быть нормой, а могут — следствием плохого индекса. 10% утилизации при нулевом трафике — норма, но те же 10% при ожидаемой высокой нагрузке — тревожный сигнал о проблемах (блокировки, deadlock, ожидание I/O), которые метрика CPU просто не покажет.
· Проклятие iowait и steal: Высокий iowait (процессор простаивает в ожидании операций ввода/вывода) формально может давать общую высокую «загрузку», хотя CPU на самом деле не занят полезной работой. В виртуальных средах steal-время показывает, что гипервизор забирает ресурсы у вашей виртуальной машины. Реагировать на это увеличением лимитов CPU — бесполезно, проблема лежит на уровне инфраструктуры.
Таким образом, «CPU utilization» без контекста похожа на измерение температуры двигателя без знания, стоит машина в пробке или мчится по автобану. И то, и другое дает высокие показания, но причины и последствия радикально разные.
Истинная катастрофа производительности часто происходит при низких показателях CPU.
Это классические сценарии:
1. Блокировки (lock contention) или deadlock в приложении или СУБД: потоки выстроились в очередь, ожидая доступа к ресурсу. CPU простаивает, запросы таймаутятся, пользователи страдают, а метрика загрузки процессора спокойно показывает 15%.
2. Проблемы с внешними зависимостями (медленные API, сбойные микросервисы, лаговые диски): приложение проводит время в ожидании ответа, не нагружая CPU.
3. Проблемы планировщика ОС или JVM (для Java-приложений).
В этих случаях мониторинг, зацикленный на утилизации, будет молчать, пока бизнес теряет деньги. Это наглядно доказывает его нерелевантность как индикатора инцидента.
Ключевой сдвиг парадигмы заключается в отказе от метрик утилизации ресурсов в пользу метрик производительности и удовлетворенности пользователей. На первое место должны выходить:
1. Latency (задержка): P95, P99 времена ответа приложения. Рост задержек — это прямой сигнал о проблеме, независимо от того, как ведет себя CPU.
2. Throughput (пропускная способность): RPS (запросов в секунду), TPS (транзакций). Падение throughput при стабильной или растущей нагрузке — явный инцидент.
3. Rate of Errors: Процент ошибок (5xx, 4xx, таймауты). Это конечный результат многих проблем, которые CPU может и не заметить.
4. Saturation (насыщение): Длина очередей, количество ожидающих потоков. Это более точный показатель «перегруженности», чем утилизация CPU. Очередь на 1000 запросов — инцидент, даже если CPU загружен на 60%.
Это — метрики бизнеса. Они отвечают на вопрос «Что чувствует пользователь?», а не «Как поживает наше железо?». Высокая утилизация CPU становится проблемой только тогда и только в том случае, когда она отрицательно коррелирует с этими ключевыми метриками: вызывает рост latency, падение throughput или увеличение ошибок.
Поэтому объявлять инцидент по факту превышения порога в 80-90% утилизации CPU — архаичная и опасная практика. Она ведет к «холиварам» между разработчиками и сисопами, бессмысленному масштабированию «вслепую» и игнорированию реальных, но тихих катастроф.
· Деградировать «CPU Utilization» до вспомогательной, диагностической метрики. Ее место на информационных дашбордах, а не в правилах алертинга.
· Строить алерты на основе метрик производительности (Latency, Errors, Saturation). Это страхует от пропуска реальных инцидентов.
· Использовать утилизацию CPU в связке с другими данными (профилировщики, трейсинг, логи) для последующего анализа причин возникших проблем с производительностью. Высокая утилизация — не причина звонить в колокол, а повод взять в руки отладчик и профилировщик, когда проблема уже обнаружена другими средствами.
Таким образом, переход от религии утилизации к культу производительности — это признак зрелости инженерной культуры. Это понимание, что цель инфраструктуры — не быть красивой и ненагруженной, а эффективно и предсказуемо обслуживать бизнес-логику. И судить о ее здоровье нужно по конечному результату, а не по абстрактной загруженности одной из ее многочисленных шестеренок.
Взято с основного технического канала Postgres DBA (возможны правки в исходной статье).
Настоящее исследование осуществлено с применением инструментария pg_expecto, обеспечивающего строгую методологию репрезентативного нагрузочного тестирования. Данный инструмент позволил провести сравнительный анализ двух дискретных конфигураций СУБД PostgreSQL в контролируемых и идентичных условиях, моделирующих устойчивую OLAP-нагрузку. Ниже представлено краткое изложение методологии эксперимента, включая описание стенда, генерации нагрузочного паттерна и ключевых варьируемых параметров, что обеспечивает полную воспроизводимость и верифицируемость полученных результатов. Основной целью являлась эмпирическая проверка гипотезы о влиянии реконфигурации областей памяти (shared_buffers и work_mem) на комплексные показатели производительности системы.
Для данной OLAP-нагрузки и текущей конфигурации сервера снижение размера shared_buffers с 4 ГБ до 1-2 ГБ, с одновременным увеличением work_mem, приведет к росту общей производительности системы. Основная цель — не просто уменьшить кэш БД, а перенаправить высвободившуюся оперативную память на выполнение операций в памяти и ослабить нагрузку на подсистему ввода-вывода.
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 30
vm.dirty_background_ratio = 10
vm.vfs_cache_pressure = 100
vm.swappiness = 10
read_ahead_kb = 4096
work_mem
----------
32MB
shared_buffers
----------------
4GB
work_mem
----------
256MB
shared_buffers
----------------
2GB
Среднее снижение операционной скорости при shared_buffers=2GB(work_mem=256MB) составило 38.38%.
Среднее увеличение ожиданий типа IO при shared_buffers=2GB(work_mem=256MB) составило 22.70%.
Среднее снижение ожиданий типа IPC при shared_buffers=2GB(work_mem=256MB) составило 4.78%.
Среднее снижение IOPS при shared_buffers=2GB(work_mem=256MB) составило 3.29%.
Среднее снижение пропускной способности(MB/s) при shared_buffers=2GB(work_mem=256MB) составило 313.74%.
Нагрузка соответствует OLAP-сценарию (аналитические запросы, большие объёмы данных).
В обоих экспериментах наблюдался рост нагрузки (Load average увеличился с 5 до 22).
Параметры экспериментов:
Эксперимент-1: shared_buffers = 4GB, work_mem = 32MB
Эксперимент-2: shared_buffers = 2GB, work_mem = 256MB
Высокий I/O wait (wa): 100% наблюдений с wa > 10%.
Корреляция ожиданий IO и записи (bo): высокая (0.6533), система ограничена производительностью записи на диск.
Состояние процессов (b): слабая корреляция с ожиданиями IO (0.2611), количество процессов в состоянии непрерываемого сна не возрастает значительно.
Отношение прочитанных блоков к изменённым: 177.98, подтверждение OLAP-нагрузки.
Высокий I/O wait (wa): 97.27% наблюдений с wa > 10%.
Корреляция ожиданий IO и записи (bo): высокая (0.6719), система также ограничена записью.
Состояние процессов (b): очень высокая корреляция с ожиданиями IO (0.8774), процессы всё чаще переходят в состояние непрерываемого сна (ожидание диска).
Отношение прочитанных блоков к изменённым: 268.01, нагрузка ещё более ориентирована на чтение.
Уменьшение shared_buffers с 4GB до 2GB привело к усилению корреляции между ожиданием IO и блокированными процессами.
В обоих случаях система ограничена производительностью записи, но во втором эксперименте дисковые ожидания сильнее влияют на состояние процессов.
Свободная RAM: менее 5% в 100% наблюдений.
Свопинг (swap in/out): используется незначительно (в 9.01% и 1.8% наблюдений соответственно).
Свободная RAM: менее 5% в 100% наблюдений.
Свопинг: не используется (0% наблюдений).
Оба эксперимента показывают критически низкое количество свободной RAM.
Свопинг практически отсутствует, что может указывать на эффективное использование файлового кэша ОС.
Hit Ratio: 55.36% (критически низкий).
Корреляция hit/read: очень высокая (0.9725), кэширование связано с большим чтением с диска.
Hit Ratio: 38.58% (ещё ниже, критически низкий).
Корреляция hit/read: очень высокая (0.8698), аналогичная картина.
Уменьшение shared_buffers с 4GB до 2GB привело к снижению Hit Ratio на ~16.78%.
В обоих случаях кэширование недостаточно эффективно для данной нагрузки.
Корреляция LWLock и user time: очень высокая (0.9775).
Корреляция LWLock и system time: очень высокая (0.9092).
Очередь процессов (r): превышение числа ядер CPU в 16.22% наблюдений.
System time (sy): не превышает 30% (все наблюдения).
Корреляция LWLock и user time: очень высокая (0.8574).
Корреляция LWLock и system time: высокая (0.6629).
Очередь процессов (r): превышение числа ядер CPU в 3.64% наблюдений.
System time (sy): не превышает 30% (все наблюдения).
В Эксперименте-1 выше корреляция LWLock с системным временем, что может указывать на большее количество системных вызовов и переключений контекста.
Очередь процессов (r) чаще превышает число ядер CPU в Эксперименте-1, но в обоих случаях это не является критичным.
Уменьшение shared_buffers с 4GB до 2GB:
Привело к снижению Hit Ratio (с 55.36% до 38.58%).
Усилило корреляцию между ожиданием IO и блокированными процессами.
Не вызвало существенных изменений в использовании свопинга и свободной RAM.
Увеличение work_mem с 32MB до 256MB:
Не компенсировало снижение эффективности кэширования при уменьшении shared_buffers.
Не привело к значительным изменениям в поведении CPU и очереди процессов.
Общий характер нагрузки (OLAP) подтверждается высоким отношением чтения к записи и сильной зависимостью производительности от операций ввода-вывода.
Диск данных: vdd (100 ГБ, LVM-том 99 ГБ, точка монтирования /data)
Конфигурация сервера:
8 CPU ядер
8 ГБ RAM
Отдельные диски для WAL (/wal) и логов (/log)
Параметры сравнения:
Эксперимент 1: shared_buffers = 4 ГБ, work_mem = 32 МБ
Эксперимент 2: shared_buffers = 2 ГБ, work_mem = 256 МБ
Продолжительность тестов: ≈110 минут каждый
Эксперимент 1 (shared_buffers=4GB, work_mem=32MB):
Средняя утилизация диска: 90-94% → 80% (снижение к концу теста)
Средний IOPS: ≈3500 операций/сек
Средняя пропускная способность: ≈130 МБ/с → 180 МБ/с (рост к концу)
Среднее время ожидания чтения: 9-14 мс
Среднее время ожидания записи: 6-7 мс
Средняя длина очереди: ≈43
Средняя загрузка CPU на IO: ≈24%
Эксперимент 2 (shared_buffers=2GB, work_mem=256MB):
Средняя утилизация диска: 93-97% (стабильно высокая)
Средний IOPS: ≈3400 операций/сек
Средняя пропускная способность: ≈139 МБ/с → 95-149 МБ/с (колебания)
Среднее время ожидания чтения: 10-19 мс
Среднее время ожидания записи: 7-10 мс
Средняя длина очереди: ≈33 → 61 (рост)
Средняя загрузка CPU на IO: ≈28% → 9% (снижение)
Эксперимент 1:
Тип ограничения: Пропускная способность диска
Корреляция скорость-MB/s: Очень высокая (0.8191)
Корреляция скорость-IOPS: Слабая (0.4128)
Вывод: Производительность определяется объемом передаваемых данных
Эксперимент 2:
Тип ограничения: Количество операций ввода-вывода
Корреляция скорость-IOPS: Очень высокая (0.9256)
Корреляция скорость-MB/s: Слабая (0.1674)
Вывод: Нагрузка чувствительна к количеству IO операций
Эксперимент 1 (shared_buffers=4GB):
Утилизация диска снижается с 94% до 80% к концу теста
Пропускная способность растет с 132 МБ/с до 180 МБ/с
Загрузка CPU на IO снижается с 28% до 18%
Стабильные показатели IOPS и времени отклика
Эксперимент 2 (shared_buffers=2GB):
Высокая и стабильная утилизация диска (93-97%)
Колебания пропускной способности (139 → 95 → 149 МБ/с)
Значительный рост длины очереди (33 → 61)
Увеличение времени ожидания чтения (10 → 19 мс)
Снижение загрузки CPU на IO (28% → 9%)
Утилизация диска: Повысилась и стабилизировалась на высоком уровне
Время отклика: Увеличилось время ожидания операций чтения
Длина очереди: Выросла в 1.8 раза к концу теста
Загрузка CPU на IO: Снизилась в 3 раза
Характер нагрузки: Сместился с пропускной способности на IOPS-ограниченный режим
Стабильность пропускной способности: Ухудшилась, появились значительные колебания
Обеспечивает более предсказуемую пропускную способность
Демонстрирует улучшение производительности в ходе теста
Оптимальна для операций, требующих последовательного чтения больших объемов данных
Меньшая длина очереди и время отклика
Создает более высокую и стабильную нагрузку на диск
Приводит к увеличению времени отклика операций
Смещает характер нагрузки в сторону большего количества мелких операций
Снижает нагрузку на CPU для операций ввода-вывода
Увеличивает глубину очереди запросов к диску