4Данный документ содержит анализ влияния параметра ядра Linux vm.vfs_cache_pressure на производительность СУБД PostgreSQL при имитации OLAP-нагрузки. Исследование фокусируется на системных метриках (I/O, память, CPU) и выявляет оптимальные настройки для заданной конфигурации оборудования.
Глоссарий терминов | Postgres DBA | Дзен
Часть 1 - Общая постановка исследования и результаты производительности СУБД и инфраструктуры.
Часть 3 - Анализ производительности подсистемы IO для файловой системы /data
Часть 2 - Анализ паттернов производительности инфраструктуры
Задача
Проанализировать влияние параметра vm.vfs_cache_pressure на производительность СУБД и инфраструктуры при синтетической нагрузке, имитирующей OLAP.
Входные данные для анализа
Сводный отчета по нагрузочному тестированию подготовленный pg_pexpecto по окончании нагрузочного тестирования:
- Метрики производительности и ожиданий СУБД
- Метрики vmstat
- Метрики iostat
- Корреляционный анализ ожиданий СУБД
- Корреляционный анализ метрик vmstat
- Корреляционный анализ метрик iostat
Общий анализ инфраструктуры при разном значении vm.vfs_cache_pressure
1. Влияние на IO-ожидания (wa)
Общая проблема: Во всех трёх экспериментах 100% наблюдений показывают wa > 10%, что свидетельствует о системном ограничении дисковой подсистемы.
Сравнение корреляций при разных значениях vm.vfs_cache_pressure:
vm.vfs_cache_pressure=50:
- Корреляция IO-wa: -0,0772 (отсутствует/отрицательная) ✅
- Корреляция IO-b: 0,0609 (слабая/средняя) ℹ️
- Корреляция IO-bi: 0,3650 (слабая/средняя) ℹ️
- Корреляция IO-bo: 0,2693 (слабая/средняя) ℹ️
vm.vfs_cache_pressure=100:
- Корреляция IO-wa: -0,9020 (отсутствует/отрицательная) ✅
- Корреляция IO-b: 0,2611 (слабая/средняя) ℹ️
- Корреляция IO-bi: 0,2730 (слабая/средняя) ℹ️
- Корреляция IO-bo: 0,6533 (высокая) ⚠️
vm.vfs_cache_pressure=150:
- Корреляция IO-wa: -0,7379 (отсутствует/отрицательная) ✅
- Корреляция IO-b: 0,0000 (отсутствует/отрицательная) ✅
- Корреляция IO-bi: 0,5074 (высокая) ⚠️
- Корреляция IO-bo: 0,5532 (высокая) ⚠️
Вывод: Увеличение vfs_cache_pressure усиливает корреляцию IO-ожиданий с операциями чтения/записи (bi/bo), что указывает на более агрессивное управление кэшем файловой системы.
2. Паттерны использования процессов в состоянии D (непрерываемый сон)
Наблюдаемый феномен:
· При vfs_cache_pressure=50: ALARM по регрессионной линии (R²=0,7, угол наклона 39,83)
· При vfs_cache_pressure=100: R²=0,03, угол наклона 10,38 (норма)
· При vfs_cache_pressure=150: R²=0,00, угол наклона 0,00 (норма)
Объяснение с точки зрения управления кэшем:
- При низком значении vfs_cache_pressure(50) ядро менее агрессивно вытесняет кэш файловой системы
- Это приводит к накоплению большего объёма кэшированных данных
При OLAP-нагрузке с интенсивным чтением это вызывает:
- Более частые блокировки процессов в состоянии D при обращении к диску
- Увеличение времени ожидания из-за конкуренции за IO-ресурсы
При значениях 100 и 150 кэш вытесняется активнее, что снижает конкуренцию и количество процессов в состоянии D
3. Производительность дисковой подсистемы и кэширования
Общие характеристики нагрузки (все эксперименты):
- Соотношение чтения к записи: ~180:1 (типичный OLAP-паттерн)
- Очень высокая корреляция скорости операций с чтением (0,85-0,88)
- Очень высокая корреляция скорости операций с записью (0,98-0,99)
- Система ограничена производительностью диска
Влияние pressure на эффективность shared buffers:
- HIT RATIO shared buffers: 55-58% (критически низкий во всех случаях)
- Корреляция shared_blks_hit - shared_blks_read: 0,96-0,97 (очень высокая)
- Вывод: vfs_cache_pressure практически не влияет на HIT RATIO PostgreSQL, так как shared buffers управляются отдельно от кэша файловой системы
Ключевые выводы по экспериментам
Лучшие показатели у pressure=100:
- Отсутствие роста процессов в состоянии D
- Умеренные корреляции с операциями чтения/записи
- Стабильное поведение системы
Проблемные зоны (все эксперименты):
- Критически низкий HIT RATIO shared buffers (55-58%)
- 100% наблюдений с wa > 10%
- Система ограничена производительностью диска
Рекомендации по оптимизации для OLAP-нагрузки
1. Настройки операционной системы:
Установить vm.vfs_cache_pressure = 100 (компромиссное значение)
Пересмотреть настройки vm.dirty_*:
- Уменьшить vm.dirty_background_ratio с 10 до 5
- Уменьшить vm.dirty_ratio с 30 до 20
- Это снизит латентность записи
Проверить и оптимизировать параметры файловой системы
2. Настройки PostgreSQL для OLAP:
- Увеличить shared_buffers с 4GB до 6GB (при 8GB RAM)
- Увеличить work_mem с 32MB до 128-256MB для сложных сортировок
- Увеличить effective_cache_size до 6-7GB
- Рассмотреть увеличение max_parallel_workers_per_gather с 1 до 2-4
- Установить random_page_cost = 1.0 (если используются SSD)
3. Аппаратные улучшения:
- Рассмотреть переход на более быстрые диски (NVMe SSD)
- Увеличить объём оперативной памяти с 8GB
- Проверить балансировку нагрузки между дисками данных и WAL
Итоговая рекомендация:
Проблема с производительностью IO является системной и требует комплексного подхода. Настройка vfs_cache_pressure даёт некоторый эффект, но не решает основную проблему нехватки оперативной памяти для кэширования данных при OLAP-нагрузке.
Анализ влияния vfs_cache_pressure на управление RAM
1. Использование оперативной памяти
Общая ситуация:
- Во всех экспериментах свободная RAM < 5% в более 50% наблюдений - это норма для сервера с активной нагрузкой
- Оперативная память практически полностью используется (7-7.2GB из 8GB)
Динамика memory_swpd (использование свопа):
- vfs_cache_pressure=50: Рост с 209 MB до 347 MB (+138 MB за 110 минут)
- vfs_cache_pressure=100: Рост с 260 MB до 328 MB (+68 MB за 111 минут)
- vfs_cache_pressure=150: Рост с 246 MB до 338 MB (+92 MB за 110 минут)
Анализ скорости роста:
- Наиболее медленный рост swpd при vfs_cache_pressure=100 (68 MB за период)
- Наиболее быстрый рост при vfs_cache_pressure=50 (138 MB за период)
- Промежуточный рост при vfs_cache_pressure=150 (92 MB за период)
Стабильность использования памяти:
Наиболее стабильное поведение при vfs_cache_pressure=100:
- Наименьший рост использования свопа
- Плавное изменение memory_swpd без резких скачков
- Более предсказуемое управление памятью
Наименее стабильное поведение при vfs_cache_pressure=50:
- Быстрый рост использования свопа
- Более агрессивное вытеснение данных в своп
2. Свопинг (swap in/out)
Статистика по экспериментам:
vfs_cache_pressure=50:
- swap in: 10% наблюдений
- swap out: 6.36% наблюдений
- Баланс смещен в сторону чтения из свопа
При vfs_cache_pressure=100:
- swap in: 9.01% наблюдений
- swap out: 1.80% наблюдений
- Минимальный объем записи в своп
vfs_cache_pressure=150:
- swap in: 10% наблюдений
- swap out: 11.82% наблюдений
- Наибольший объем записи в своп
Объяснение различий:
1. vfs_cache_pressure=50:
- Низкое давление на кэш файловой системы
- Ядро менее агрессивно освобождает кэш
- Чаще приходится читать из свопа (высокий swap in)
- Относительно низкий swap out - меньше данных вытесняется
2. vfs_cache_pressure=100:
- Оптимальный баланс
- Кэш управляется эффективно
- Минимальный swap out - редко требуется запись в своп
- Умеренный swap in - меньше обращений к свопу
3. vfs_cache_pressure=150:
- Высокое давление на кэш файловой системы
- Ядро агрессивно освобождает кэш
- Высокий swap out - активная запись в своп
- Высокий swap in - частые чтения из свопа
3. Кэширование и dirty pages
Взаимодействие vfs_cache_pressure с настройками vm.dirty_*:
Текущие настройки:
- vm.dirty_ratio=30 (запись блокируется при 30% dirty pages)
- vm.dirty_background_ratio=10 (фоновая запись при 10%)
- read_ahead_kb=4096 (4MB read-ahead)
Влияние pressure на dirty pages:
1. vfs_cache_pressure=50:
- Медленное освобождение кэша
- Больше данных остается в памяти
- Более высокий риск достижения dirty_ratio
- Потенциальные блокировки записи при всплесках нагрузки
2. vfs_cache_pressure=100:
- Сбалансированное управление
- Кэш освобождается своевременно
- Меньше риск блокировок из-за dirty pages
- Оптимально для текущих настроек dirty_*
3. vfs_cache_pressure=150:
- Быстрое освобождение кэша
- Меньше данных в кэше файловой системы
- Чаще требуется чтение с диска
- Возможна излишняя агрессивность для OLAP
Оптимальные значения для OLAP-нагрузки:
Для OLAP с большим чтением рекомендуется:
- vfs_cache_pressure=100-120 (компромиссное значение)
- read_ahead_kb=8192-16384 (увеличение для последовательного чтения)
- vm.dirty_background_ratio=5 (более частая фоновая запись)
- vm.dirty_ratio=20 (раньше начинать синхронную запись)
Обоснование:
- OLAP характеризуется последовательным чтением больших объемов данных
- Большой read-ahead улучшает производительность последовательного чтения
- Более низкие dirty_* значения снижают латентность записи
- vfs_cache_pressure=100 обеспечивает баланс между кэшированием и доступной памятью
Сравнение паттернов использования memory_cache и memory_buff
Общие наблюдения:
- memory_cache: 7.1-7.2GB (доминирующий компонент)
- memory_buff: 1-8MB (незначительный объем)
- memory_free: 121-139MB (минимально)
Изменения во времени:
1. vfs_cache_pressure=50:
- memory_cache: относительно стабилен (7160-7223 MB)
- memory_buff: снижается с 8 до 1 MB к концу периода
- Постепенное перераспределение из buff в cache
2. vfs_cache_pressure=100:
- memory_cache: более вариабелен (7147-7255 MB)
- memory_buff: стабильнее (1-4 MB)
- Более динамичное управление кэшем
3. vfs_cache_pressure=150:
- memory_cache: наибольшая вариативность (7154-7220 MB)
- memory_buff: умеренные колебания (2-4 MB)
- Наиболее агрессивное управление памятью
Ключевые выводы по управлению памятью:
Рекомендуемые настройки для OLAP:
- vfs_cache_pressure = 100 (оптимальный баланс)
- Уменьшить vm.dirty_background_ratio до 5
- Уменьшить vm.dirty_ratio до 20
- Увеличить read_ahead_kb до 8192 или 16384
- Рассмотреть увеличение оперативной памяти
Обоснование рекомендаций:
1. vfs_cache_pressure=100 показывает наилучший баланс:
- Минимальный рост использования свопа
- Наименьший объем записи в своп (swap out)
- Стабильное использование memory_cache
- Эффективное управление кэшем файловой системы
2. Для OLAP с последовательным чтением:
- Увеличение read-ahead улучшает производительность
- Более агрессивные настройки dirty pages снижают латентность
- Достаточный объем кэша файловой системы важен для повторного доступа к данным
3. Текущая конфигурация памяти не оптимальна:
- 8GB RAM недостаточно для OLAP-нагрузки
- Активное использование свопа снижает производительность
- Рекомендуется увеличение RAM до 16-32GB
Анализ влияния vfs_cache_pressure на CPU
1. Нагрузка на CPU
Ключевые наблюдения:
- Все эксперименты показывают очень высокую корреляцию LWLock с user time (0.96-0.98)
- Все эксперименты показывают очень высокую корреляцию LWLock с system time (0.91-0.95)
Распределение CPU времени по экспериментам:
vfs_cache_pressure=50:
- us (user time): 21-61% (среднее ~30%)
- sy (system time): 5-10% (среднее ~7%)
- wa (I/O wait): 17-31% (среднее ~27%)
- id (idle): 12-42% (среднее ~35%)
vfs_cache_pressure=100:
- us (user time): 25-57% (среднее ~35%)
- sy (system time): 5-10% (среднее ~7%)
- wa (I/O wait): 18-29% (среднее ~25%)
- id (idle): 14-41% (среднее ~33%)
vfs_cache_pressure=150:
- us (user time): 22-58% (среднее ~32%)
- sy (system time): 5-10% (среднее ~7%)
- wa (I/O wait): 16-28% (среднее ~24%)
- id (idle): 13-41% (среднее ~34%)
Влияние vfs_cache_pressure:
- User time: Наиболее высокий при pressure=100 (среднее 35%)
- System time: Практически идентичен во всех случаях (~7%)
- I/O wait: Наименьший при pressure=150 (среднее 24%)
- Idle time: Наибольший при pressure=50 (среднее 35%)
Вывод: Увеличение pressure снижает I/O wait, но незначительно увеличивает user time, что указывает на более активную обработку данных приложением.
2. Переключения контекста
Общая картина:
- Высокая корреляция переключений контекста с прерываниями (cs-in) во всех экспериментах (0.95-0.97)
- При vfs_cache_pressure=150 появляется слабая/средняя корреляция cs-sy (0.0244)
Влияние управления кэшем на переключения контекста:
Механизм влияния:
1. vfs_cache_pressure=50:
- Менее агрессивное управление кэшем
- Меньше системных вызовов для управления памятью
- Переключения контекста в основном вызваны прерываниями от дисковых операций
2. vfs_cache_pressure=100:
- Сбалансированное управление кэшем
- Умеренное количество системных вызовов для управления памятью
- Прерывания остаются основной причиной переключений контекста
3. vfs_cache_pressure=150:
- Агрессивное управление кэшем
- Увеличение системных вызовов для управления памятью
- Появление корреляции cs-sy указывает на рост времени ядра на управление памятью
Объяснение корреляции cs-sy при pressure=150:
Ядро тратит больше времени на:
- Вытеснение страниц из кэша файловой системы
- Управление списками страниц памяти
- Обработку запросов на выделение/освобождение памяти
- Это приводит к увеличению system time и связанных с ним переключений контекста
3. Очередь выполнения (run queue)
Статистика по экспериментам:
vfs_cache_pressure=50:
- Проценты превышения ядер CPU: 7.27%
- Максимальное значение procs_r: 10 процессов
- Более стабильная очередь выполнения
vfs_cache_pressure=100:
- Проценты превышения ядер CPU: 16.22%
- Максимальное значение procs_r: 11 процессов
- Наименее стабильная очередь выполнения
vfs_cache_pressure=150:
- Проценты превышения ядер CPU: 14.55%
- Максимальное значение procs_r: 11 процессов
- Промежуточная стабильность
Анализ стабильности:
Наиболее стабильная очередь при pressure=50:
- Наименьший процент превышения ядер CPU (7.27%)
- Более равномерное распределение нагрузки
- Меньше конкуренции за CPU ресурсы
Наименее стабильная очередь при pressure=100:
- Наибольший процент превышения ядер CPU (16.22%)
- Более выраженная конкуренция за CPU
- Возможные задержки в обработке запросов
Рекомендации по балансировке vfs_cache_pressure
Для конфигурации: 8 CPU ядер, 8GB RAM, OLAP-нагрузка с интенсивным чтением
1. Оптимальный диапазон значений: vfs_cache_pressure = 90-110
Обоснование:
Компромисс между производительностью и стабильностью:
- vfs_cache_pressure=50: лучшая стабильность очереди выполнения, но выше I/O wait
- vfs_cache_pressure=150: ниже I/O wait, но выше нагрузка на ядро (system time)
- vfs_cache_pressure=100: баланс между этими крайностями
2. Сопутствующие настройки для OLAP-нагрузки:
Настройки операционной системы:
- vm.swappiness = 10 (уже установлено, оптимально для серверов)
- vm.dirty_background_ratio = 5 (уменьшить с 10 для более частой фоновой записи)
- vm.dirty_ratio = 20 (уменьшить с 30 для снижения латентности записи)
- read_ahead_kb = 16384 (увеличить для последовательного чтения OLAP)
Настройки PostgreSQL для 8 CPU ядер:
- max_parallel_workers_per_gather = 2-4 (увеличить с 1 для OLAP)
- max_worker_processes = 16 (уже установлено, оптимально)
- max_parallel_workers = 16 (уже установлено, оптимально)
- work_mem = 64-128MB (увеличить с 32MB для сложных сортировок)
Рекомендации по аппаратному обеспечению:
Для текущей нагрузки рекомендуется:
- Увеличение оперативной памяти до 16-32GB
- Использование быстрых NVMe SSD для данных и WAL
- Рассмотреть распределение нагрузки на несколько дисковых массивов
Итоговая рекомендация:
Установить vm.vfs_cache_pressure = 100 с мониторингом следующих метрик:
1. I/O wait time (должен снижаться или стабилизироваться)
2. Количество процессов в состоянии D (непрерываемый сон)
3. Частота свопинга (должна снижаться)
4. Hit ratio shared buffers PostgreSQL (целевой > 80%)
При сохранении высокого I/O wait (>25%) рекомендуется:
1. Сначала увеличить оперативную память
2. Затем улучшить дисковую подсистему
3. Только после этого экспериментировать с другими значениями vfs_cache_pressure
Рекомендации по оптимизации vfs_cache_pressure для заданной конфигурации
1. Оптимальное значение vfs_cache_pressure
Рекомендуемое значение: vm.vfs_cache_pressure = 100
Обоснование выбора:
Для конфигурации 8 CPU / 8GB RAM / OLAP-нагрузка:
Баланс стабильности и производительности:
- При pressure=100 наблюдается наиболее сбалансированное поведение системы
- Наименьший рост использования свопа (+68MB против +138MB при 50)
- Минимальный объем записи в своп (1.80% против 6.36% и 11.82%)
- Умеренная нагрузка на CPU (средний I/O wait 25%)
Оптимальное управление памятью:
- Кэш файловой системы эффективно управляется без излишней агрессивности
- Обеспечивается достаточное кэширование для OLAP с интенсивным чтением
- Стабильное использование memory_cache (~7.2GB)
Соответствие характеристикам нагрузки:
- Соотношение чтение/запись ∼180:1 требует хорошего кэширования
- Ограниченный объем RAM (8GB) требует эффективного управления кэшем
- Отдельные разделы для /data и /wal позволяют оптимизировать каждую подсистему
2. Взаимодействие с другими настройками
a. Взаимодействие с effective_cache_size=6GB
Текущая ситуация:
- effective_cache_size=6GB (75% от доступной RAM)
- shared_buffers=4GB (50% от доступной RAM)
- Кэш файловой системы: ~3GB (оставшаяся память за вычетом shared_buffers и служебных нужд)
Рекомендации по настройке:
1. Согласованность с vfs_cache_pressure:
- При pressure=100 эффективный кэш файловой системы будет занимать 2-3GB
- effective_cache_size=6GB является реалистичной оценкой (4GB shared buffers + 2GB FS cache)
- Рекомендация: Оставить effective_cache_size=6GB без изменений
2. Мониторинг фактического использования:
- Следить за соотношением hits в shared buffers и FS cache
- При росте нагрузки может потребоваться увеличение shared_buffers за счет уменьшения effective_cache_size
b. Настройка vm.swappiness=10
Текущее значение: vm.swappiness=10 (уже оптимально)
Взаимодействие с vfs_cache_pressure:
1. vfs_cache_pressure=100:
- swappiness=10 обеспечивает минимальное использование свопа
- В сочетании с pressure=100 дает оптимальный баланс:
- Кэш файловой системы управляется через pressure
- Своп используется только в крайних случаях
- Рекомендация: Сохранить swappiness=10
2. Альтернативные сценарии:
- Если увеличить RAM до 16GB+: можно уменьшить swappiness до 1-5
- При высокой частоте свопинга (>20%): снизить pressure до 80-90
- При недостатке памяти для процессов: временно увеличить swappiness до 20-30
c. Настройка read_ahead_kb=4096
Текущее значение: read_ahead_kb=4096 (4MB)
Оптимизация для OLAP-нагрузки:
1. Рекомендуемое значение: read_ahead_kb=16384 (16MB)
Обоснование:
- OLAP-нагрузка характеризуется последовательным чтением больших объемов данных
- Увеличение read-ahead уменьшает количество обращений к диску
- Для современных HDD/SSD 16MB является оптимальным для последовательного чтения
2. Взаимодействие с vfs_cache_pressure:
- Большой read-ahead увеличивает объем данных в кэше файловой системы
- pressure=100 обеспечивает своевременное освобождение устаревших данных
- Комбинация pressure=100 + read_ahead_kb=16384 оптимальна для OLAP
3. Дополнительные рекомендации:
- Для дисков с высокой латентностью: можно увеличить до 32768 (32MB)
- Для SSD с низкой латентностью: достаточно 8192 (8MB)
- Мониторинг влияния через iostat -x (поле "avgqu-sz")
Комплексные рекомендации для всей системы
Для операционной системы:
vm.vfs_cache_pressure = 100
vm.swappiness = 10
read_ahead_kb = 16384
vm.dirty_background_ratio = 5
vm.dirty_ratio = 20
vm.dirty_expire_centisecs = 3000 (оставить)
Для PostgreSQL (дополнительные оптимизации):
shared_buffers = 4GB (оставить, 50% от RAM)
work_mem = 64MB (увеличить с 32MB для OLAP)
effective_cache_size = 6GB (оставить)
max_parallel_workers_per_gather = 2 (увеличить с 1 для OLAP)
random_page_cost = 1.1 (оставить для SSD/быстрых дисков)
effective_io_concurrency = 300 (оставить)
Важное замечание: При ограниченном объеме RAM (8GB) основным ограничением является не настройка pressure, а физический объем памяти. Для существенного улучшения производительности OLAP-нагрузки рекомендуется увеличение RAM до 16-32GB.
Послесловие
Проведённый анализ показывает, что настройка vm.vfs_cache_pressure = 100 обеспечивает наилучший баланс для текущей конфигурации, смягчая, но не устраняя системные ограничения. Ключевой проблемой остаётся недостаток оперативной памяти, делающий аппаратный апгрейд наиболее эффективным путём к значительному повышению производительности.
Исследование лишний раз подтверждает, что производительность СУБД — это комплексная проблема на стыке приложения, ОС и железа. «Волшебной» настройки не существует, есть лишь поиск равновесия в конкретных условиях. Оптимизация vfs_cache_pressure — это настройка дирижёра, но оркестру (аппаратной части) всё ещё не хватает инструментов.