# Конфигурация памяти в контексте механизма _Эксплуатация и наблюдаемость · PostgreSQL Knowledge Base_ **TL;DR:** Четыре параметра памяти решают разные задачи. shared_buffers - общий кеш страниц на весь кластер. work_mem - лимит на ОДНУ операцию сортировки или хеша в ОДНОМ запросе, и его легко умножить на сотни. maintenance_work_mem - для vacuum и build индекса. effective_cache_size - подсказка планировщику, не аллокация. ## Память настраивают по механизму, а не по рецепту «Поставь work_mem побольше» - совет без понимания того, как параметр расходуется, и так роняют сервер. Каждый из четырёх параметров живёт в своей подсистеме. ## shared_buffers - общий кеш Один блок разделяемой памяти на весь кластер - это и есть буферный кеш ([buffer-cache](/courses/postgres/kb/buffer-cache.md)). Сюда кладутся страницы таблиц и индексов, чтобы не читать их с диска повторно. Выделяется один раз при старте. Типичная отправная точка - около четверти ОЗУ машины; больше не всегда лучше, потому что под кешем работает ещё и страничный кеш ОС. ## work_mem - самый коварный Лимит памяти на **одну** операцию: сортировку (`ORDER BY`), хеш-соединение (см. [join-algorithms](/courses/postgres/kb/join-algorithms.md)), хеш-агрегацию. Ключевое слово - «одну». В одном запросе таких операций может быть несколько, и каждая берёт до `work_mem`. Умножь на число параллельных соединений - и получишь реальный аппетит. ``` пиковый расход ≈ work_mem × (операций в запросе) × (одновременных запросов) ``` Поэтому `work_mem = 1GB` на сервере с сотней коннектов - это заявка на OOM, а не оптимизация. Параметр поднимают точечно: глобально скромный, а под конкретный тяжёлый отчёт - `SET work_mem` в его сессии. ## Что происходит при нехватке work_mem Операция не падает - она «проливается» на диск (temp-файлы). Сортировка становится внешней, хеш разбивается на пакеты. Запрос отработает, но медленно. Сигнал виден в плане (`Sort Method: external merge Disk: NNNN kB`) и в счётчиках: ```sql SELECT datname, temp_files, pg_size_pretty(temp_bytes) AS temp FROM pg_stat_database WHERE temp_files > 0; ``` Растущий `temp_files` под нагрузкой - прямая подсказка, что `work_mem` мал для текущих запросов. Включённый `log_temp_files = 0` пишет каждый пролив в лог. ## maintenance_work_mem - для обслуживания Отдельный лимит для `VACUUM`, `CREATE INDEX`, `ALTER TABLE`. Этих операций мало и они не параллелятся клиентами, поэтому его ставят заметно выше `work_mem`: больше памяти - быстрее vacuum собирает мёртвые идентификаторы, быстрее строится индекс. ## effective_cache_size - подсказка, не аллокация Этот параметр **ничего не выделяет**. Он сообщает планировщику, сколько суммарно памяти под кеш доступно (shared_buffers плюс страничный кеш ОС). По нему планировщик оценивает, насколько вероятно, что нужные страницы уже в памяти, и охотнее выбирает index scan вместо seq scan. Заниженное значение отпугивает планировщик от индексов. Как находить запросы, которым не хватает work_mem - [pg-stat-map](/courses/postgres/kb/pg-stat-map.md). Почему запрос вообще выбрал сортировку и индекс - это уже планировщик и его стоимостная модель (см. [cost-model](/courses/postgres/kb/cost-model.md)). ## Команды ```sql SHOW work_mem; ``` Текущий лимит на одну операцию сортировки/хеша ```sql SET work_mem = '64MB'; ``` Поднять лимит только в текущей сессии - под конкретный тяжёлый запрос ```sql SELECT datname, temp_files, temp_bytes FROM pg_stat_database WHERE temp_files > 0; ``` Проливы на диск из-за нехватки work_mem ```sql SHOW effective_cache_size; ``` Подсказка планировщику об общем объёме кеша (не аллокация) ## См. также - [Карта pg_stat_* и pg_stat_statements](/courses/postgres/kb/pg-stat-map.md) - [Каталог анти-паттернов (cheat sheet)](/courses/postgres/kb/anti-patterns.md) - [Буферный кеш и вытеснение](/courses/postgres/kb/buffer-cache.md) - [Стоимостная модель](/courses/postgres/kb/cost-model.md)