База PostgreSQL 10 выросла до 5 ТБ за месяц опытной эксплуатации. Около 3 ТБ заняла одна таблица. Система обрабатывала 4 млн первичных документов в месяц, хотя проект рассчитывали на 10 ТБ данных за год.
Эти цифры приводит статья Infostart «Особенности разработки больших и высоконагруженных баз 1С + PostgreSQL». В ней работало до 1000 активных пользователей. Это не 30 000 одновременных сеансов и не доказательство такого предела для одной базы 1С:ERP.
Для настройки важнее другое: сколько сеансов одновременно выполняют операции, как быстро растут таблицы и что загружено во время задержки. Ни размер штата, ни число заведённых учётных записей этого не показывают.
Ниже — стартовый профиль для сервера с 128 ГБ RAM, 32 vCPU и NVMe RAID 10. Его нельзя копировать вслепую. Часть параметров пересчитывается по памяти, а autovacuum настраивается по накоплению старых версий строк.
Два кейса нельзя складывать в один
Первый кейс описывает реальную систему на PostgreSQL 10. В ней работало до 1000 активных пользователей, а поток первичных данных достигал 4 млн записей в месяц.
Второй материал — статья «Инженерный контур 1С. Часть 2», опубликованная Infolimp 5 сентября 2026 года. Автор прямо называет торговый контур обобщённым сценарием, а не отчётом о внедрении.
В этом сценарии база занимает 1,8 ТБ. PostgreSQL 16 работает на Linux, сервер получил 128 ГБ RAM, 32 vCPU и NVMe RAID 10. На пике автор закладывает 350 одновременно активных сеансов и свыше 40 000 транзакций маркировки в сутки.
| Кейс | СУБД и нагрузка | Наблюдаемый симптом | Что можно перенести |
|---|---|---|---|
| Высоконагруженная база из статьи Infostart | PostgreSQL 10, до 1000 активных пользователей, около 4 млн первичных данных в месяц | База выросла до 5 ТБ за месяц, одна таблица заняла около 3 ТБ | Подход к настройке autovacuum при быстром росте таблиц |
| Обобщённый торговый контур Infolimp | PostgreSQL 16, база 1,8 ТБ, пик 350 активных сеансов | p95 проведения отгрузки достиг 14,2 секунды при цели менее 2,5 секунды | Профиль памяти для хоста со 128 ГБ RAM |
| Тот же торговый контур | Более 40 000 транзакций маркировки в сутки | Интерфейс и обработчики API зависают на 5–12 секунд | Порядок поиска ожиданий, тяжёлых запросов и проблем очистки |
Вывод: цифры описывают разные системы. Их нельзя объединить в утверждение о работе одной базы с 30 000 одновременных пользователей.
Даже формулировка «1000 активных пользователей» требует осторожности. Она не сообщает, сколько людей одновременно проводили документы и сколько соединений выполняли запросы в конкретную секунду. Во втором кейсе этот показатель назван прямо — 350 сеансов на пике.
Поэтому начните не с общего числа пользователей. Зафиксируйте одновременные сеансы, поток операций, размер крупнейших таблиц и профиль нагрузки на CPU и диски. Для воспроизводимой проверки подойдёт нагрузочный сценарий для активных сеансов 1С.
Память считают от роли сервера
В обобщённом кейсе PostgreSQL стартовал с shared_buffers = 128MB, work_mem = 4MB и checkpoint_timeout = 5min. Такие значения не учитывают сервер со 128 ГБ памяти и нагрузку 1С:ERP.
Руководство Andko по настройке PostgreSQL для 1С предлагает отдавать СУБД до 70% физической памяти на выделенном сервере. Если платформа 1С работает на том же хосте, долю снижают до 50%.
Для выделенного сервера расчёт выглядит так:
128 ГБ × 0,70 = 89,6 ГБ
Это не значение одного параметра. Это верхняя рамка памяти для процессов PostgreSQL, кэшей и рабочих операций.
Для совмещённого хоста расчёт другой:
128 ГБ × 0,50 = 64 ГБ
Остаток нужен серверу 1С, операционной системе и сопутствующим службам. Переносить лимит 89,6 ГБ на совмещённый сервер нельзя.
Для shared_buffers руководство Andko предлагает 25% доступной RAM. На хосте из кейса расчёт даёт:
128 ГБ × 0,25 = 32 ГБ
Этот результат совпадает со значением из материала Infolimp. Значит, 32GB можно взять как старт для описанного хоста, но не как норму для любого сервера.
| Параметр | Исходное значение | Старт для хоста из кейса | Основание | Что проверить |
|---|---|---|---|---|
shared_buffers | 128MB | 32GB | 25% от 128 ГБ по руководству Andko; то же значение у Infolimp | Хватает ли памяти ОС и другим процессам |
effective_cache_size | Не указано | 96GB | Значение из профиля Infolimp; оно равно 75% RAM | Не считать его отдельным резервом памяти |
work_mem | 4MB | 48MB | Профиль Infolimp для конкретного контура | Число параллельных сортировок и соединений |
temp_buffers | Не указано | 16MB | Профиль Infolimp | Объём временных таблиц каждого сеанса |
checkpoint_timeout | 5min | Не переносить без замеров | Исходное значение дано Infolimp, нового универсального значения нет | Частоту контрольных точек и запись WAL |
Вывод: для 128 ГБ RAM обоснован старт с shared_buffers = 32GB. Остальные значения относятся к конкретному профилю и требуют проверки под рабочей нагрузкой.
effective_cache_size не резервирует 96 ГБ поверх shared_buffers. Параметр сообщает планировщику, какой объём данных может находиться в кэше PostgreSQL и операционной системы.
С work_mem риск обратный. PostgreSQL выделяет эту память не один раз на весь сервер, а для отдельных операций сортировки и хеширования. При множестве одновременных запросов значение 48MB способно дать расход, который нельзя оценивать простым сложением с shared_buffers.
Перед включением строгого режима Huge Pages сверьте расчёт резерва памяти Linux для PostgreSQL. Ошибка в vm.nr_hugepages может оставить СУБД без нужного объёма страниц при запуске.
Диск влияет на планировщик, но не отменяет диагностику
Для SSD руководство Andko предлагает random_page_cost от 1.1 до 1.5. Для NVMe там же указано effective_io_concurrency = 200; для SATA SSD — 100, для HDD — 2.
Эти значения описывают тип накопителя, а не скорость конкретного массива. Контроллер, RAID, прошивка, очередь запросов и фоновые операции меняют фактическое поведение дисковой подсистемы.
На NVMe RAID 10 из обобщённого кейса можно начать с такого фрагмента:
random_page_cost = 1.1
effective_io_concurrency = 200
Верхняя граница random_page_cost = 1.5 пригодится для повторной проверки плана. Если план запросов не меняется, подбор десятых долей не устранит задержку сам по себе.
Не снижайте стоимость случайного чтения только потому, что в сервере стоит NVMe. Сначала сравните планы тяжёлых запросов и ожидания. Иначе настройка заставит планировщик чаще выбирать случайный доступ, хотя причина задержки лежит в блокировках или нехватке статистики.
Autovacuum настраивают по росту старых версий строк
PostgreSQL не удаляет изменённую строку сразу. Старая версия остаётся в таблице до очистки autovacuum. При большом потоке изменений такие версии увеличивают таблицы и объём работы для чтения.
В сценарии Infolimp доля неактуальных версий достигала 28–35% таблиц. В кейсе Infostart одна таблица выросла примерно до 3 ТБ, а всю базу пришлось удерживать от дальнейшего разрастания более агрессивной очисткой.
Авторы первого кейса снизили autovacuum_vacuum_scale_factor с 0.2 до 0.01. Они также подняли autovacuum_vacuum_cost_limit до 1000 и оставили autovacuum_vacuum_cost_delay = 20ms.
Это параметры тяжёлого случая. Значение 0.01 нельзя объявить общей нормой для 1С:ERP.
Руководство Andko предлагает более осторожную стартовую точку: четыре рабочих процесса autovacuum, интервал запуска 30 секунд, порог очистки 0.05 и порог анализа 0.02.
| Параметр | Осторожный старт | Значение из тяжёлого кейса | Когда менять |
|---|---|---|---|
autovacuum_max_workers | 4 | Не указано | Рабочие процессы не успевают обходить крупные таблицы |
autovacuum_naptime | 30s | Не указано | Очистка запускается реже, чем растёт объём изменений |
autovacuum_vacuum_scale_factor | 0.05 | 0.01 | При работающем autovacuum снова растёт доля старых версий |
autovacuum_analyze_scale_factor | 0.02 | Не указано | Планы строятся по устаревшей статистике |
autovacuum_vacuum_cost_limit | Проверить под диском | 1000 | Очистка отстаёт, а диск сохраняет запас по нагрузке |
autovacuum_vacuum_cost_delay | Проверить под диском | 20ms | Менять вместе с лимитом, а не отдельно |
Вывод: начните с autovacuum_vacuum_scale_factor = 0.05. Переход к 0.01 оправдан, если старые версии снова накапливаются при работающей очистке.
У порога есть неприятная особенность: он зависит от размера таблицы. Чем крупнее таблица, тем больше изменений потребуется до запуска очистки по доле строк. Поэтому один общий профиль может справляться с небольшими таблицами и опаздывать на крупнейшей.
Следите не только за фактом запуска autovacuum. Нужны скорость накопления старых версий, длительность очистки и конкуренция за диск. Если очистка постоянно работает, но отставание растёт, дальнейшее сокращение интервала лишь добавит фоновой нагрузки.
PgBouncer распределяет соединения, но не создаёт ресурсы
Репозиторий aidarsafindev/1c-pgbouncer-arbiter показывает приоритизацию запросов через три экземпляра PgBouncer. Пулы HIGH, NORMAL и LOW получают разные лимиты соединений, а TCP-арбитр на Python выбирает пул по application_name.
Демонстрация хорошо показывает границу метода. Клиент psql передаёт application_name, а 1С не делает этого тем же способом. Для 1С также нужен pool_mode = session.
В этом режиме отмена запроса через pg_cancel_backend не освобождает соединение. Репозиторий ограничивает вытеснение read-only-запросами из пула LOW; пишущие INSERT, UPDATE и DELETE не отменяются.
| Ограничение | Что происходит | Практический вывод |
|---|---|---|
1С не передаёт ожидаемый application_name | Арбитр не получает готовый признак приоритета | Нужен собственный способ классификации |
1С требует pool_mode = session | Соединение закреплено за сеансом | Отмена запроса не возвращает слот в пул |
| CPU или диск загружены на 100% | Все пулы конкурируют за исчерпанный ресурс | Приоритизация не устраняет дефицит |
| Таблицы общие для трёх пулов | Блокировки действуют на всех | Отдельный пул не изолирует данные |
| Пишущие запросы не вытесняются | Долгая запись продолжает занимать ресурс | LOW-пул не гарантирует освобождение сервера |
Вывод: PgBouncer управляет доступом к соединениям, но не лечит перегруженный CPU, диск и общие блокировки.
Если запросы образуют очередь внутри базы, сначала определите место ожидания. Граница между настройкой PostgreSQL и выносом очереди зависит от захвата строк, индексов и требований к повторной обработке.
Стартовый профиль для сервера из кейса
Для выделенного хоста с 128 ГБ RAM, 32 vCPU, PostgreSQL 16 и NVMe RAID 10 стартовый фрагмент выглядит так:
shared_buffers = 32GB
effective_cache_size = 96GB
work_mem = 48MB
temp_buffers = 16MB
random_page_cost = 1.1
effective_io_concurrency = 200
autovacuum_max_workers = 4
autovacuum_naptime = 30s
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
Это исходная точка, а не готовый конфигурационный файл. Профиль собран для базы 1,8 ТБ и пика в 350 активных сеансов. Он не подтверждает работу 30 000 одновременных пользователей.
При другом объёме RAM пересчитайте долю памяти PostgreSQL и shared_buffers. Для выделенного сервера используйте рамку до 70%, для совмещённого — до 50%, а shared_buffers начните с 25% памяти.
work_mem, temp_buffers, параметры autovacuum и ввода-вывода линейно не масштабируйте. Проверьте их повторным прогоном одинакового сценария. Для одной тяжёлой операции используйте проверку запросов PostgreSQL при медленном закрытии месяца.
После изменения сравните четыре признака:
- p95 выбранной операции приблизился к вашему нормативу.
- Старые версии строк не накапливаются между циклами autovacuum.
- Пиковый расход памяти не уводит сервер в swap и OOM.
- CPU и диск сохраняют запас при том же числе активных сеансов.
Если результат зависит от структуры таблиц, числа параллельных операций и профиля запросов, готовая статья не заменит обследование. После контрольного прогона можно заказать технический разбор настроек PostgreSQL под конкретную базу.
Главное правило простое: переносите из чужого кейса метод проверки и стартовые значения под совпадающие исходные данные. Чужое число пользователей переносить нельзя.