Для нового небольшого проекта с PostgreSQL можно взять за отправную точку для теста 4 vCPU, 16 ГБ RAM и NVMe. Это пример начальной конфигурации, а не обещание производительности: база на 20 ГБ с тяжёлыми отчётами может требовать больше ресурсов, чем база на 200 ГБ с редкими короткими запросами.
Сервер нужно выбирать по двум результатам: он выдерживает рабочую нагрузку и позволяет восстановить проект за приемлемое время. Количество ядер, объём памяти и надпись NVMe ещё не подтверждают ни первого, ни второго.
Ниже рассматривается PostgreSQL на Linux для сайтов, CRM и других прикладных систем. SQL-примеры рассчитаны на PostgreSQL 16–18. Для специализированных сборок, например под 1С, дополнительно проверяйте совместимость платформы, расширений и версии СУБД.
Какие данные собрать перед выбором сервера
Если база уже работает, измеряйте её во время обычной нагрузки и замедления. Нужны размер данных вместе с индексами, рост за месяц, количество одновременно выполняемых запросов, доля записи и время важных операций. Число зарегистрированных пользователей не заменяет эти показатели.
Подключитесь к нужной базе через psql. Для просмотра чужих сеансов потребуется роль с правами мониторинга, например pg_monitor, или администратор. Следующие запросы читают статистику:
SELECT pg_size_pretty(pg_database_size(current_database())) AS database_size;
SELECT state, wait_event_type, count(*) AS sessions
FROM pg_stat_activity
WHERE datname = current_database()
AND backend_type = 'client backend'
GROUP BY state, wait_event_type
ORDER BY sessions DESC;
SELECT temp_files,
pg_size_pretty(temp_bytes) AS temp_written,
stats_reset
FROM pg_stat_database
WHERE datname = current_database();
Первый результат показывает объём выбранной базы. Он не включает другие базы, весь каталог WAL и место для будущих операций. Второй помогает отличить активную работу от ожидания: например, Lock означает ожидание блокировки. Значение NULL само по себе не доказывает нехватку CPU.
temp_bytes — накопленный объём записи во временные файлы. Сравните два замера за известный интервал с неизменным stats_reset. Быстрый рост во время отчёта — повод проверить его план и настройки памяти. Это ещё не основание увеличивать RAM или work_mem для всех запросов.
Для нового проекта вместо статистики потребуется тестовая база с реалистичным объёмом и сценарии приложения: поиск, создание записи, отчёт, пакетная загрузка. Проверка на нескольких сотнях строк плохо предсказывает работу с миллионами.
CPU: когда нужны быстрые ядра, а когда их количество
Производительность одного ядра важна для операций, которые выполняются последовательно. Дополнительные ядра помогают обслуживать несколько запросов одновременно и выполнять подходящие параллельные планы. Но PostgreSQL не распределяет любой запрос по всем доступным ядрам.
Поэтому сравнивайте модель и поколение CPU, условия предоставления vCPU и результаты своего теста. Одинаковое число виртуальных ядер у разных тарифов не гарантирует одинаковую производительность. Для VPS уточните, разделяется ли процессорное время с соседями и есть ли ограничения длительной нагрузки.
На Linux загрузку по ядрам можно посмотреть командой из пакета sysstat:
mpstat -P ALL 1 10
Если занято одно ядро, а остальные свободны, проверьте конкретный запрос. Если во время нужной нагрузки заняты почти все ядра и запросы не ждут диска или блокировок, тест конфигурации с большим числом ядер оправдан. Устойчивая высокая доля %steal в виртуальной машине требует отдельной проверки у провайдера: гостевая ОС ждёт процессорное время.
Если pg_stat_statements уже подключён, найдите запросы с наибольшим суммарным временем выполнения:
SELECT queryid, calls,
round(total_exec_time::numeric, 1) AS total_ms,
round(mean_exec_time::numeric, 1) AS mean_ms,
left(query, 120) AS query
FROM pg_stat_statements
WHERE dbid = (SELECT oid FROM pg_database
WHERE datname = current_database())
ORDER BY total_exec_time DESC
LIMIT 10;
Смотрите одновременно число вызовов и среднее время: частый короткий запрос тоже может создавать основную нагрузку. Если расширение не настроено, для его подключения обычно требуется изменение конфигурации и перезапуск; запланируйте это отдельно.
Медленный запрос сначала изучите через EXPLAIN. Вариант EXPLAIN (ANALYZE, BUFFERS) действительно выполняет запрос, поэтому тяжёлые операции и запросы, изменяющие данные, разбирайте на тестовой копии. Новый процессор не устранит ненужный полный просмотр таблицы или ожидание длинной транзакции.
RAM: вся база не обязана помещаться в память
Для часто повторяющихся чтений полезно держать в памяти активно используемые страницы таблиц и индексов. Старые записи, к которым почти не обращаются, не обязательно постоянно хранить в кеше. Поэтому правило «RAM должна равняться размеру базы» не подходит для всех систем.
Память расходуют общий кеш PostgreSQL, кеш файловой системы, запросы, служебные процессы и соседние приложения. В контейнере ориентируйтесь также на лимит памяти контейнера: свободная RAM физического сервера не отменяет этот лимит.
Посмотрите действующие параметры:
SHOW shared_buffers;
SHOW work_mem;
SHOW hash_mem_multiplier;
SHOW effective_cache_size;
SHOW max_connections;
Для сервера, выделенного под PostgreSQL, документация предлагает начинать с shared_buffers около 25% RAM. Например, для 32 ГБ это 8 ГБ. Это старт для проверки, а не общий лимит памяти PostgreSQL. Если рядом работают приложение и другие службы, бюджет нужно уменьшить с учётом их потребления.
work_mem применяется к отдельным операциям сортировки и хеширования. У запроса таких операций может быть несколько; одновременно работают разные сеансы и параллельные процессы. Условные 100 запросов, каждый с двумя одновременными сортировками по 64 МиБ, дают до 12,5 ГиБ только на эти сортировки, ещё без дополнительных параллельных процессов. Хеширование учитывает также hash_mem_multiplier.
Поэтому увеличение work_mem проверяйте на конкретных запросах и при реальной конкуренции. effective_cache_size вообще не выделяет память: это оценка доступного кеша для планировщика.
Проверьте free -h и vmstat 1 10. В vmstat оценивайте строки после первой, которая показывает средние значения с момента загрузки. Важны доступная память и продолжающийся обмен со swap в столбцах si/so, особенно одновременно с ростом задержек. Сам факт занятого swap не доказывает текущую нехватку RAM.
При большом числе соединений оцените пул подключений, например PgBouncer, и лимиты приложения. Пул позволяет управлять числом серверных соединений; режим его работы должен быть совместим с приложением. Простое увеличение max_connections не создаёт дополнительной вычислительной мощности.
NVMe: смотрите на задержки записи и доступную ёмкость
Для PostgreSQL важна не только скорость последовательного чтения больших файлов. Запросы обращаются к страницам таблиц и индексов, а фиксация транзакций зависит от надёжной записи журнала WAL — журнала предзаписи, по которому PostgreSQL восстанавливает изменения.
При умеренной нагрузке может хватить SATA SSD. NVMe стоит выбирать, когда требуется больше операций ввода-вывода и низкие задержки. Но быстрый интерфейс не гарантирует стабильную скорость под длительной записью. У выделенного сервера уточните модель накопителей, ресурс записи и наличие защиты от потери питания — PLP. У VPS дополнительно проверьте ограничения операций ввода-вывода и пропускной способности хранилища.
Во время нагрузки посмотрите:
iostat -y -xz 1 10
Утилита входит в sysstat. Сравнивайте задержки чтения и записи, очередь запросов и показатели PostgreSQL с нормальным состоянием того же сервера. Один показатель %util не даёт надёжного ответа о насыщении NVMe или виртуального хранилища.
Не отключайте fsync и full_page_writes ради красивого теста. Это может привести к повреждению базы после сбоя. Такой результат нельзя переносить на рабочую систему с требованиями к сохранности данных. Отключение synchronous_commit — отдельный компромисс: при сбое можно потерять уже подтверждённые клиенту последние транзакции.
Дисковый бюджет считайте так: данные и индексы + ожидаемый рост + локальный WAL + временные файлы и обслуживание + ОС и журналы + свободный запас. Перестроение большого индекса или таблицы тоже может требовать дополнительного места.
Например, если расчётный максимум всех этих данных и операций составляет 300 ГБ, диск с 300 ГБ доступного места не подходит. При выбранном для проекта запасе 25% потребуется не менее 400 ГБ полезной ёмкости. Это пример планирования, а не обязательный процент PostgreSQL.
Считайте ёмкость после RAID: зеркало из двух дисков по 1 ТБ даёт примерно 1 ТБ до форматирования. RAID уменьшает последствия некоторых отказов диска, но не защищает от ошибочного удаления таблицы.
Контролируйте размер pg_wal. Сломанная архивация или отставший потребитель репликационного слота — механизма удержания журнала для репликации — могут удерживать WAL и заполнить диск. max_wal_size не является жёстким пределом этого каталога. Удалять файлы WAL вручную нельзя: сначала выясните причину удержания.
Если используются архивация или репликационные слоты, на основном сервере проверьте:
SELECT archived_count, last_archived_time,
failed_count, last_failed_time
FROM pg_stat_archiver;
SELECT slot_name, active, restart_lsn
FROM pg_replication_slots;
Рост failed_count между замерами означает новые ошибки архивации: найдите причину в журнале PostgreSQL и восстановите доставку в архив. Старое время последней архивации на простаивающей базе само по себе не доказывает сбой. Если потребитель слота отключён, а restart_lsn не меняется при продолжающейся записи, проверьте его работоспособность и удержание WAL. Не удаляйте слот без понимания, как затем восстановится его потребитель.
Как понять, какой ресурс ограничивает PostgreSQL
| Что наблюдаете | Что проверить | Следующий шаг |
|---|---|---|
| Один запрос медленный, остальные работают нормально | План, индексы, объём обрабатываемых строк, ожидание блокировок | Исправить запрос или схему доступа; затем повторить тест CPU |
| При росте нагрузки заняты все ядра, растёт время ответа | Нет ли ожидания I/O, не выполняется ли лишняя работа | Сравнить более быстрый CPU или больше ядер на том же сценарии |
| Растут swap и временные файлы, возникают ошибки нехватки памяти | Конкурентные запросы, лимиты памяти, параметры PostgreSQL и соседние процессы | Ограничить одновременную работу, исправить чрезмерные настройки; при необходимости добавить RAM |
| Запросы ждут I/O, задержки диска растут | Объём чтения, запись WAL, фоновые операции и лимиты хранилища | Уменьшить ненужный ввод-вывод или выбрать более производительное хранилище |
| Диск заполняется быстрее роста полезных данных | WAL, временные файлы, журналы, работу autovacuum — фонового обслуживания таблиц — и длинные транзакции | Найти источник роста; расширение диска использовать как запас времени, а не замену исправлению |
| CPU и диск свободны, приложение отвечает медленно | Блокировки, очередь подключений и задержку между приложением и БД | Разобрать ожидание; покупка дополнительных ресурсов может ничего не изменить |
Показатели нужно сопоставлять по времени. Снимок загрузки через полчаса после жалобы не объясняет, что происходило во время проблемы.
VPS или выделенный сервер: как проверить выбор до переноса
VPS удобен, когда его ресурсов и условий изоляции достаточно для проекта. Выделенный сервер имеет смысл при длительной высокой нагрузке, большом объёме RAM или требованиях к конкретным дискам и их схеме. Физическая машина сама по себе не создаёт резервный узел и не гарантирует автоматическое восстановление.
Приложение и PostgreSQL могут работать на одном VPS, если не мешают друг другу. Разделение полезно при конкуренции за ресурсы или разных требованиях к обслуживанию, но добавляет сетевую задержку. Проверяйте время операций со стороны приложения. При сетевом подключении проверьте firewall и pg_hba.conf: доступ к PostgreSQL должен быть разрешён только нужным узлам приложения и администрирования.
До переноса подготовьте тестовую копию и проведите проверку:
- Восстановите реалистичный объём данных с нужными индексами и расширениями. Сохраните версию PostgreSQL и настройки, чтобы сравнение серверов было корректным.
- Воспроизведите обычную и пиковую нагрузку приложения. Укажите заранее допустимое время ключевых операций и число одновременно выполняемых запросов.
- Измеряйте не только среднюю задержку, но и p95/p99 — время, быстрее которого завершаются 95% и 99% операций. Проверяйте ошибки и тайм-ауты.
- Повторите тест при резервном копировании и обычных фоновых работах. Несколько секунд тестирования не показывают устойчивую производительность.
- Изменяйте один существенный фактор за раз и сравнивайте результат. Зафиксируйте запас на ожидаемый рост.
pgbench подходит для воспроизводимого теста, особенно с собственными SQL-сценариями. Его стандартный результат нельзя напрямую переводить в число пользователей вашего приложения. Маленький набор данных, полностью попавший в кеш, также не проверяет поведение большой базы на диске.
Для сравнения конфигураций посмотрите VPS/VDS HSTQ и выделенные серверы HSTQ. Перед заказом укажите профиль нагрузки, объём данных, рост и требования к восстановлению. Модель CPU, параметры хранилища, резервные копии и объём администрирования согласуйте для выбранной услуги: базовая поддержка инфраструктуры не заменяет сопровождение PostgreSQL.
Как выбрать резервное копирование под допустимую потерю данных
Сначала определите два показателя. RPO — какой период последних изменений допустимо потерять. RTO — за какое время нужно вернуть приложение в работу. Например, «не больше пяти минут данных и не больше часа простоя» — уже требования, по которым можно проверить схему.
| Способ | Когда подходит | Ограничение |
|---|---|---|
| Логический дамп через pg_dump | Небольшая база, перенос отдельных объектов, допустимо вернуться к моменту копии | Восстановление данных и индексов может быть долгим; обычный дамп не даёт произвольного отката по времени |
| Физическая базовая копия и непрерывный архив WAL | Нужно восстановление к выбранному моменту — PITR | Нужны подходящая базовая копия и непрерывная цепочка WAL; физическая копия не служит способом перехода на другую основную версию PostgreSQL |
| Реплика PostgreSQL | Нужно сократить время возвращения сервиса после отказа основного узла | Ошибочное изменение тоже реплицируется; нужны отдельные резервные копии и процедура переключения |
При ежедневном дампе можно потерять почти сутки изменений, а при пропущенном запуске — больше. Для PITR используют, например, pgBackRest: он управляет базовыми копиями, архивом WAL и восстановлением. Один архив WAL без базовой копии не восстанавливает кластер. Обычный pg_dump не заменяет базовую физическую копию для PITR.
Храните копии и необходимые WAL вне сервера с базой. Не рассчитывайте на обычное копирование каталога работающего PostgreSQL: файловая копия требует согласованной процедуры. Отдельно сохраните конфигурацию, список расширений и доступы к хранилищу. У логических дампов глобальные объекты, включая роли, сохраняются отдельно, например через pg_dumpall --globals-only.
При архивации завершёнными сегментами WAL на малоактивной базе отправка может задерживаться. archive_timeout позволяет принудительно завершать сегменты по времени, но сам по себе не гарантирует RPO: архив ещё должен успешно попасть во внешнее хранилище.
Если pgBackRest уже настроен, проверьте его конфигурацию и доступные копии. Здесь app — пример имени stanza, то есть набора настроек вашего кластера:
sudo -u postgres pgbackrest --stanza=app check
sudo -u postgres pgbackrest --stanza=app info
check должен завершиться успешно; он в том числе проверяет доставку тестового сегмента WAL. В info проверьте дату подходящей копии и доступные диапазоны WAL. Ошибка проверки требует разбора журналов и доступов к репозиторию. Успешный результат этих команд ещё не заменяет восстановление.
Как проверить восстановление до аварии
Проводите проверку на отдельном сервере или изолированном кластере. Исходную базу и единственную резервную копию не изменяйте. Подготовьте совместимую версию PostgreSQL, нужные расширения, кодировку и правила сортировки, достаточно места и доступ к архиву. Для первой репетиции проще использовать ту же основную версию, что у источника.
Для логического дампа в формате custom, созданного с pg_dump -Fc, можно сначала проверить восстановление данных. Следующий пример выполняется только на отдельном тестовом сервере с обычной установкой PostgreSQL в Linux. Файл заранее размещён по указанному пути и доступен пользователю postgres; имя restore_check ещё не занято. Выполняйте команды по очереди и останавливайтесь при любой ошибке:
sudo -u postgres pg_restore --list /var/lib/postgresql/restore-check/appdb.dump
sudo -u postgres createdb --template=template0 restore_check
sudo -u postgres pg_restore --exit-on-error \
--no-owner --no-privileges --no-tablespaces \
--dbname=restore_check \
/var/lib/postgresql/restore-check/appdb.dump
sudo -u postgres psql -X -v ON_ERROR_STOP=1 \
--dbname=restore_check -c 'ANALYZE;'
--list показывает оглавление, но не проверяет восстановимость всех данных. Успех — завершившийся без ошибок импорт и последующая проверка содержимого. Если дамп ссылается на роли, например в политиках доступа, подготовьте их заранее.
Флаги --no-owner, --no-privileges и --no-tablespaces упрощают первую проверку: исходные владельцы и права не воспроизводятся, объекты размещаются в стандартном хранилище тестовой базы. Для полной репетиции воспроизведите нужные роли, владение, разрешения и размещение объектов; проверьте подключение под пользователем приложения.
При ошибке версии используйте совместимые клиентские утилиты и сервер. При отсутствии расширения установите его совместимую версию на тестовый сервер. Ошибки ролей и прав исправляйте по сохранённой схеме доступа. Не объявляйте восстановление успешным, пока ошибки импорта не устранены.
Для физической копии с PITR проведите отдельную репетицию: выберите точку после завершения базовой копии, восстановите кластер из внешнего хранилища и убедитесь, что проигрывание WAL дошло до нужного момента. Если PostgreSQL сообщает о недостающем WAL или недостижимой цели восстановления, проверьте цепочку, диапазон хранения, временную зону цели и выбранную копию. Нельзя обходить эту проблему удалением WAL или применять pg_resetwal как обычный способ восстановления.
После технического запуска подключите тестовую копию приложения, отключив реальные рассылки, платежи и фоновые задания. Проверьте важные записи, число ключевых записей и последнюю известную операцию, чтение и тестовую запись. Для PITR подготовьте две контрольные записи с подтверждёнными транзакциями до и после выбранной точки: первая должна присутствовать, вторая — отсутствовать.
Засекайте весь путь: получение сервера, скачивание копии, распаковку, восстановление, проигрывание WAL и запуск приложения. Условные 500 ГБ архива при эффективной скорости передачи 100 МБ/с потребуют около 83 минут только на передачу. Требование восстановиться за полчаса такая схема уже не выполняет.
Повторяйте репетицию после смены основной версии PostgreSQL, расширений, инструмента резервного копирования или хранилища. В журнале проверки сохраняйте дату копии, достигнутую точку восстановления, ошибки и полное время возврата приложения в работу.