Autovacuum postgresql 1с настройка
Устанавливать будем сборку от компании Postgres Professional. На странице с версией для 1С:Предприятие найдем информацию об установке на CentOS 7 свежей версии PostgreSQL.
Подключим репозитории и установим PostgreSQL 9.6:
Базовая настройка PostgreSQL
Инициализируем служебные базы данных с русской локализацией:
Запускаем службу PostgreSQL и добавляем его в автозагрузку:
Задаем пароль пользователю postgres, для того чтобы была возможность подключаться к серверу удаленно:
Для возможности пользователю postgres авторизовываться по паролю отредактируем файл pg_hba.conf:
в открывшемся файле раскомментируем и изменим строки:
host all all 127.0.0.1/32 ident на host all all 127.0.0.1/32 md5
host all all 0.0.0.0/0 ident на host all all 0.0.0.0/0 md5
Оптимизация настроек PostgreSQL (postgresql.conf) для 1С:Предприятие
Здесь будут настройки для PostgreSQL, работающей в виртуальной машине ESXi 6.5.
Ресурсы выделенные для ВМ:
процессор — 8 vCPU;
диск для ОС — 50 GB на LUN аппаратном RAID1 из SAS HDD;
диск для БД — 170 GB на программном RAID1 из SSD
диск для логов — 100 GB на программном RAID1 из SSD
Для редактирования настроек выполним команду:
Закомментированные параметры, которые будем изменять необходимо активировать.
Процессор
autovacuum_max_workers = 4
autovacuum_max_workers = NCores/4..2 но не меньше 4
Количество процессов автовакуума. Общее правило — чем больше write-запросов, тем больше процессов. На read-only базе данных достаточно одного процесса.
ssl = off
Выключение шифрования. Для защищенных ЦОД’ов шифрование бессмысленно, но приводит к увеличению загрузки CPU
Память
shared_buffers = 12GB
shared_buffers = RAM/4
Количество памяти, выделенной PgSQL для совместного кеша страниц. Эта память разделяется между всеми процессами PgSQL. Операционная система сама кеширует данные, поэтому нет необходимости отводить под кэш всю наличную оперативную память.
temp_buffers = 256MB
Максимальное количество страниц для временных таблиц. Т.е. это верхний лимит размера временных таблиц в каждой сессии.
work_mem = 64MB
work_mem = RAM/32..64 или 32MB..128MB
Лимит памяти для обработки одного запроса. Эта память индивидуальна для каждой сессии. Теоретически, максимально потребная память равна max_connections * work_mem, на практике такого не встречается потому что большая часть сессий почти всегда висит в ожидании. Это рекомендательное значение используется оптимайзером: он пытается предугадать размер необходимой памяти для запроса, и, если это значение больше work_mem, то указывает экзекьютору сразу создать временную таблицу. work_mem не является в полном смысле лимитом: оптимайзер может и промахнуться, и запрос займёт больше памяти, возможно в разы. Это значение можно уменьшать, следя за количеством создаваемых временных файлов:
maintenance_work_mem = 2GB
maintenance_work_mem = RAM/16..32 или work_mem * 4 или 256MB..4GB
Лимит памяти для обслуживающих задач, например по сбору статистики (ANALYZE), сборке мусора (VACUUM), создания индексов (CREATE INDEX) и добавления внешних ключей. Размер выделяемой под эти операции памяти должен быть сравним с физическим размером самого большого индекса на диске.
effective_cache_size = 36GB
effective_cache_size = RAM — shared_buffers
Оценка размера кеша файловой системы. Увеличение параметра увеличивает склонность системы выбирать IndexScan планы. И это хорошо.
Диски
effective_io_concurrency = 5
Оценочное значение одновременных запросов к дисковой системе, которые она может обслужить единовременно. Для одиночного диска = 1, для RAID — 2 или больше.
random_page_cost = 1.3
random_page_cost = 1.5-2.0 для RAID, 1.1-1.3 для SSD
Стоимость чтения рандомной страницы (по-умолчанию 4). Чем меньше seek time дисковой системы тем меньше (но > 1.0) должен быть этот параметр. Излишне большое значение параметра увеличивает склонность PgSQL к выбору планов с сканированием всей таблицы (PgSQL считает, что дешевле последовательно читать всю таблицу, чем рандомно индекс). И это плохо.
autovacuum = on
autovacuum_naptime = 20s
Время сна процесса автовакуума. Слишком большая величина будет приводить к тому, что таблицы не будут успевать вакуумиться и, как следствие, вырастет bloat и размер таблиц и индексов. Малая величина приведет к бесполезному нагреванию.
bgwriter_delay = 20ms
Время сна между циклами записи на диск фонового процесса записи. Данный процесс ответственен за синхронизацию страниц, расположенных в shared_buffers с диском. Слишком большое значение этого параметра приведет к возрастанию нагрузки на checkpoint процесс и процессы, обслуживающие сессии (backend). Малое значение приведет к полной загрузке одного из ядер.
bgwriter_lru_multiplier = 4.0
bgwriter_lru_maxpages = 400
Параметры, управляющие интенсивностью записи фонового процесса записи. За один цикл bgwriter записывает не больше, чем было записано в прошлый цикл, умноженное на bgwriter_lru_multiplier, но не больше чем bgwriter_lru_maxpages.
synchronous_commit = off
Выключение синхронизации с диском в момент коммита. Создает риск потери последних нескольких транзакций (в течении 0.5-1 секунды), но гарантирует целостность базы данных, в цепочке коммитов гарантированно отсутствуют пропуски. Но значительно увеличивает производительность.
wal_keep_segments = 256
wal_keep_segments = 32..256
Максимальное количество сегментов WAL между checkpoint. Слишком частые checkpoint приводят к значительной нагрузке на дисковую подсистему по записи. Каждый сегмент имеет размер 16MB
wal_buffers = 16 MB
Объём разделяемой памяти, который будет использоваться для буферизации данных WAL, ещё не записанных на диск. Значение по умолчанию, равное -1, задаёт размер, равный 1/32 (около 3%) от shared_buffers, но не меньше, чем 64 КБ и не больше, чем размер одного сегмента WAL (обычно 16 МБ). Это значение можно задать вручную, если выбираемое автоматически слишком мало или велико, но при этом любое положительное число меньше 32 КБ будет восприниматься как 32 КБ. Этот параметр можно задать только при запуске сервера.
Содержимое буферов WAL записывается на диск при фиксировании каждой транзакции, так что очень большие значения вряд ли принесут значительную пользу. Однако значение как минимум в несколько мегабайт может увеличить быстродействие при записи на нагруженном сервере, когда сразу множество клиентов фиксируют транзакции. Автонастройка, действующая при значении по умолчанию (-1), в большинстве случаев выбирает разумные значения.
default_statistics_target = 1000
Устанавливает целевое ограничение статистики по умолчанию, распространяющееся на столбцы, для которых командой ALTER TABLE SET STATISTICS не заданы отдельные ограничения. Чем больше установленное значение, тем больше времени требуется для выполнения ANALYZE, но тем выше может быть качество оценок планировщика. Значение этого параметра по умолчанию — 100.
checkpoint_completion_target = 0.9
Степень «размазывания» checkpoint’a. Скорость записи во время checkpoint’а регулируется так, что бы время checkpoint’а было равно времени, прошедшему с прошлого, умноженному на checkpoint_completion_ target.
min_wal_size = 4G
max_wal_size = 8G
min_wal_size = 512MB .. 4G
max_wal_size = 2 * min_wal_sizeМинимальное и максимальный объем WAL файлов. Аналогично checkpoint_segments
fsync = on
Выключение параметра приводит к росту производительности, но появляется значительный риск потери всех данных при внезапном выключении питания. Внимание: если RAID имеет кеш и находиться в режиме write-back, проверьте наличие и функциональность батарейки кеша RAID контроллера! Иначе данные записанные в кеш RAID могут быть потеряны при выключении питания, и, как следствие, PgSQL не гарантирует целостность данных.
row_security = off
Отключение контроля разрешения уровня записи
enable_nestloop = off
Включает или отключает использование планировщиком планов соединения с вложенными циклами. Полностью исключить вложенные циклы невозможно, но при выключении этого параметра планировщик не будет использовать данный метод, если можно применить другие. По умолчанию этот параметр имеет значение on.
Блокировки
max_locks_per_transaction = 256
Максимальное число блокировок индексов/таблиц в одной транзакции
Настройки под платформу 1С
standard_conforming_strings = off
Разрешить использовать символ \ для экранирования
escape_string_warning = off
Не выдавать предупреждение о использовании символа \ для экранирования
Настройка безопасности
Сделаем так, чтобы сервер PostgreSQL был виден только для сервера 1С: Предприятие, установленного на этой же машине.
listen_addresses = ‘localhost’
Если сервер 1С: Предприятие установлен на другой машине или существует необходимость подключиться подключиться к серверу СУБД с помощью оснастки PGAdmin, то вместо localhost нужно указать адрес этой машины.
Хранение базы данных
PostgreSQL как и почти любая СУБД критична к дисковой подсистеме, поэтому для повышения быстродействия СУБД разместим систему PostgreSQL, логи и сами базы на разные диски.
Оптимизация производительности PostgreSQL для работы с 1С:Предприятие
PostgreSQL приобретает все большую популярность как СУБД для использования в связке с 1С:Предприятие. При этом одним из самых частых нареканий является низкая производительность этого решения. Во многом это связано с тем, что настройки PostgreSQL по умолчанию не являются оптимальными, а обеспечивают запуск и работу СУБД на минимальной конфигурации. Поэтому имеет смысл потратить некоторое количество времени на оптимизацию производительности сервера, тем более что это не очень сложно.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.
Существуют разные рекомендации по оптимизации PostgreSQL для совместной работы с 1С, мы будем опираться на официальные рекомендации, изложенные на ИТС, также можно использовать онлайн-калькулятор для быстрого расчета некоторых параметров. Если данные калькулятора и рекомендации 1С будут расходиться - то предпочтение будет отдано рекомендациям 1С.
Для тестирования мы использовали систему:
- CPU - Core i5-4670 - 3.4/3.8 ГГц
- RAM - 32 ГБ DDR3
- Системный диск - SSD WD Green 120 ГБ
- Диск для данных - 2 х SSD Samsung 860 EVO 250 ГБ - RAID1
- СУБД - PostgresPro 11.6
- Платформа - 8.3.16.1148
- ОС - Debian 10 x64
Прежде всего выполним тестирование с параметрами по умолчанию:
Полученный результат - 22,32 по Гилеву высоким не назовешь, для субъективного контроля мы использовали конфигурацию Розница 2.2 с базой реального торгового предприятия объемом в 8 ГБ, в целом работу можно было признать удовлетворительной, но местами наблюдалась некоторая "задумчивость", особенно при открытии динамических списков.
Перейдем к оптимизации. Все изменения следует вносить в файл postgesql.conf, который располагается в Linuх для сборки от 1С по пути /etc/postgres/1x/main, а для сборки от PostgresPro в /var/lib/pgpro/1c-1x/data. В Windows данный файл располагается в каталоге данных, по умолчанию это C:\Program Files\PostgreSQL 1C\1х\data. Все параметры указаны в порядке их следования в конфигурационном файла.
Одним из основных параметров, используемых при расчетах, является объем оперативной памяти. При этом следует использовать то значение, которое вы готовы выделить серверу СУБД, за вычетом ОЗУ используемой ОС и другими службами, скажем, сервером 1С. В нашем случае будет использоваться значение в 24 ГБ.
Затем рассчитаем значения отдельных параметров с помощью калькулятора, для чего укажем ОС и версию Postgres, тип накопителя, количество доступной памяти и количество ядер процессора. В поле DB Type указываем Data Warehouses, количество соединений можем проигнорировать, так как вычисляемый результат будет значительно расходиться с рекомендациями 1С.
Теперь можно приступать к редактированию файла конфигурации. Многие значения в нем закомментированы и содержат значения по умолчанию, при изменении таких параметров данные строки следует раскомментировать.
Максимальное число соединений, 1С рекомендует указанные выше значения, мы установили 1000.
Объем памяти для совместного кеша страниц, разделяется между всеми процессами Postgres, рекомендуемое значение - четверть доступного объема памяти, в нашем случае 6 ГБ.
Верхний лимит для временных таблиц в каждой сессии, рекомендуется фиксированное значение.
Указывает объем памяти, который может быть использован для запроса прежде, чем будут задействованы временные файлы на диске. Применяется для каждого соединения и каждой операции, поэтому итоговый объем используемой памяти может существенно превосходить указанное значение. Это один из тех параметров, вычисляемое значение которого калькулятором существенно отличается от рекомендаций 1С. Для объема памяти в 24 ГБ рекомендуемыми значениями будут 375 - 750 МБ, мы выбрали 512 МБ.
Объем памяти для обслуживающих задач (автовакуум, реиндексация и т.д.), указываем рекомендованный калькулятором объем, в нашем случае 2 ГБ.
Максимальное количество открытых файлов на один процесс, в сборке от PostgresPro для Linux это значение по умолчанию.
Параметры процесса фоновой записи, который отвечает за синхронизацию страниц в shared_buffers с диском.
Допустимое число одновременных операций ввода/вывода. Для жестких дисков указывается по количеству шпинделей, для массивов RAID5/6 следует исключить диски четности. Для SATA SSD это значение рекомендуется указывать равным 200, а для быстрых NVMe дисков его можно увеличить до 500-1000. При этом следует понимать, что высокие значения в сочетании с медленными дисками сделают обратный эффект, поэтому подходите к этой настройке грамотно.
Важно! Параметр effective_io_concurrency настраивается только в среде Linux, в Windows системах его значение должно быть равно нулю.
Настройки фоновых рабочих процессов, выбираются исходя из количества процессорных ядер, берем значения из калькулятора. Выше указаны настройки для четырехъядерного СРU.
Заставляет сервер добиваться физической записи изменений на диск. Выключение данной опции хотя и позволяет повысить производительность, но значительно увеличивает риск неисправимой порчи данных при внезапном выключении питания.
Альтернатива отключению fsync, позволяет серверу не ждать сохранения данных на диске, прежде чем сообщить клиенту об успешном завершении операции. Позволяет достаточно безопасно повысить производительность работы. В случае внезапного выключения питания могут быть потеряны несколько последних транзакций, но сама база останется в рабочем состоянии, также, как и при штатной отмене потерянных транзакций.
Задает размер буферов журнала предзаписи (WAL, он же журнал транзакций), если оставить эту настройку без изменений, то сервер будет автоматически устанавливать это значение в 1/32 от shared_buffers, но не менее 64 КБ и не более размера одного сегмента WAL в 16 МБ.
Указывает задержку в мс перед записью транзакций на диск при числе открытых транзакций, указанных во второй опции. Имеет смысл при количестве транзакций более 1000 в секунду, на меньших значениях эффекта не имеет.
Минимальный и максимальный размер файлов журнала предзаписи. Указываем значения из калькулятора, в нашем случае это 4 ГБ и 16 ГБ.
Скорость записи изменений на диск, рассчитывается как время между точками сохранения транзакций (чекпойнты) умноженное на данный показатель, позволяет растянуть процесс записи по времени и тем самым снизить одномоментную нагрузку на диски. В нашем случае использовано рекомендованное калькулятором максимальное значение 0,9.
Стоимость последовательного чтения с диска, является относительным числом, вокруг которого определяются все остальные переменные стоимости, данное значение является значением по умолчанию.
Стоимость случайного чтения с диска, чем ниже это число, тем более вероятно использование сканирования по индексу, нежели полное считывание таблицы, однако не следует указывать слишком низких, не соответствующих реальной производительности дисковой подсистемы, значений, иначе вы можете получить обратный эффект, когда производительность упрется в медленный случайный доступ.
Так как это относительные значения, но не имеет смысла устанавливать random_page_cost ниже seq_page_cost, однако при применении производительных SSD имеет смысл понизить стоимость обоих значений, чтобы повысить приоритет дисковых операций по отношению к процессорным.
Для производительных SSD можно использовать значения:
Но еще раз напомним, данные значения не являются панацеей и должны устанавливаться осмысленно, с реальным пониманием производительности дисковой подсистемы сервера, бездумное копирование настроек способно привести к обратному эффекту.
Определяет эффективный размер кеша, который может использоваться при одном запросе. Этот параметр не влияет на размер выделяемой памяти, не резервирует ее, а служит для ориентировочной оценки доступного размера кеша планировщиком запросов. Чем он выше, тем большая вероятность использования сканирования по индексу, а не последовательного сканирования. При расчете следует использовать выделенный серверу объем RAM, а не полный объем ОЗУ. В нашем случае это 18 ГБ.
Включение автовакуума, это очень важный для производительности базы параметр. Не отключайте его!
Количество рабочих процессов автовакуума, рассчитывается по числу процессорных ядер, не менее 4, в нашем случае 4.
Время сна процессов автовакуума, большое значение будет приводить к неэффективно работе, слишком малое только повысит нагрузку без видимого эффекта.
Отключает политику защиты на уровне строк, данная опция не используется платформой и ее отключение дает некоторое повышение производительности.
Максимальное количество блокировок в одной транзакции, рекомендация от 1С.
Данные опции специфичны для 1С и регулируют использование символа \ для экранирования.
Сохраним файл конфигурации и перезапустим PostgreSQL, в Linux это можно выполнить командами:
В Windows штатными средствами операционной системы, либо скриптами из поставки сборки PostgreSQL:
После чего снова выполним тестирование производительности, на этот раз мы получили следующий результат:
Как видим, достаточно несложные действия по оптимизации добавили серверу около 30% производительности, субъективные ощущения от работы с конфигурацией Розница также повысились, исчезло ощущение "задумчивости", повысилась отзывчивость системы.
Указанные выше настройки и параметры являются базовым набором для оптимизации PostgreSQL при совместной работе с 1С:Предприятие и доступны даже начинающим администраторам. Для выполнения этих действий не требуется глубокого понимания работы СУБД, достаточно просто правильно рассчитать ряд значений. Данные рекомендации основаны на официальных и рекомендуются в качестве базовой настройки сервера СУБД сразу после инсталляции.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.
To remind you, we started with problems related to isolation, made a digression about low-level data structure, discussed row versions in detail and observed how data snapshots are obtained from row versions.
Then we explored in-page vacuum (and HOT updates) and vacuum. Now we'll look into autovacuum.
We've already mentioned that normally (i. e., when nothing holds the transaction horizon for a long time) VACUUM usually does its job. The problem is how often to call it.
If we vacuum a changing table too rarely, its size will grow more than desired. Besides, a next vacuum operation may require several passes through indexes if too many changes were done.
If we vacuum the table too often, the server will constantly do maintenance rather than useful work — and this is no good either.
Note that launching VACUUM on schedule by no means resolves the issue because the workload can change with time. If the table starts to change more intensively, it must be vacuumed more often.
Autovacuum is exactly the technique that enables us to launch vacuuming depending on how intensive the table changes are.
When autovacuum is turned on (the autovacuum configuration parameter set), the autovacuum launcher daemon process is started, which plans the work. Vacuuming itself is done by autovacuum worker processes, several instances of which can run in parallel.
The autovacuum launcher process composes a list of databases where any activity takes place. The activity is determined from statistics, and to collect it, the track_counts parameter must be set. Never turn off autovacuum and track_counts, otherwise, the autovacuum feature won't work.
Once every autovacuum_naptime seconds, autovacuum launcher starts (using the postmaster process) a worker process for each database on the list. In other words, if there is some activity in a database, worker processes will be sent to it at an interval of autovacuum_naptime seconds. To this end, if a few (N) active databases are available, worker processes are launched N times as often as every autovacuum_naptime seconds. But the total number of simultaneously running worker processes is limited by the autovacuum_max_workers parameter.
When started, a worker process connects to the database assigned to it and starts with composing a list of:
- All the tables, materialized views and TOAST tables that require vacuuming.
- All tables and materialized views that require analysis (TOAST tables are not analyzed since they are always reached with index access).
If the process could not do all the work planned in autovacuum_naptime seconds, the autovacuum launcher process will send one more worker process to this database, and they will work together. «Together» just means that the second process will build its own list and work through it. So, only different tables will be processed in parallel, but there is no parallelism at the level of one table — if one of the worker processes is already handling a table, another process will skip it and proceed further.
Now let's clarify in more detail what is meant by «requires vacuuming» and «requires analysis».
Recently the patch was committed that allows the vacuum to process indexes in parallel with background workers.
Vacuuming is considered to be required if the number of dead (i. e., outdated) tuples exceeds the specified threshold. The statistics collector is permanently keeping track of the number of dead tuples, which is stored in the pg_stat_all_tables table. And two parameters specify the threshold:
- autovacuum_vacuum_threshold defines an absolute value (the number of tuples).
- autovacuum_vacuum_scale_factor defines the share of rows in the table.
With the default settings, autovacuum_vacuum_threshold = 50 and autovacuum_vacuum_scale_factor = 0.2. autovacuum_vacuum_scale_factor is, certainly, the most important here — it's this parameter that is critical for large tables (and it's them that possible issues are associated with). The value of 20% seems unduly high, and most likely it will need to be considerably reduced.
Optimal values of the parameters may vary for different tables and depend on the table sizes and specifics of the changes. It makes sense to set generally suitable values and, if the need arises, do special tweaking of the parameters at the level of certain tables by means of storage parameters:
- autovacuum_vacuum_threshold and toast.autovacuum_vacuum_threshold.
- autovacuum_vacuum_scale_factor and toast.autovacuum_vacuum_scale_factor.
Besides, you can turn autovacuum off at the table level (although we can hardly think of a reason why it could be necessary):
- autovacuum_enabled and toast.autovacuum_enabled.
To formalize all the above, let's create a view that shows which tables need vacuuming at this point in time. It will use the function that returns the current value of the parameter and takes into account that the value can be redefined at the table level:
And this is the view:
The situation with automatic analysis is similar. Those tables are considered to require analysis whose number of updated (since the last analysis) tuples exceeds the threshold specified by two similar parameters: pg_stat_all_tables.n_mod_since_analyze >= autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * pg_class.reltupes .
The default settings of automatic analysis are somewhat different: autovacuum_analyze_threshold = 50 and autovacuum_analyze_scale_factor = 0.1. They can also be defined at the level of storage parameters of separate tables:
- autovacuum_analyze_threshold
- autovacuum_analyze_scale_factor
Let's also create a view for analysis:
Let's set the following parameter values for experiments:
Now let's create a table similar to the one used last time and insert one thousand rows into it. Autovacuum is turned off at the table level, and we will be turning it on by ourselves. Without this, the examples will not be reproducible since autovacuuming can be triggered at a bad time.
This is what our view for vacuuming will show:
Attention here should be given to two things. First, max_dead_tup = 0 although 3% of 1000 rows make 30 rows. The thing is that we do not have statistics on the table yet since INSERT does not update it on its own. Until the table gets analyzed, zeros will remain since pg_class.reltuples = 0. But let's look at the second view for analysis:
Since 1000 rows have been changed (added) in the table, which is greater than zero, automatic analysis must be triggered. Let's check this:
After a short pause we can see that the table has been analyzed and correct 20 rows are shown in max_dead_tup instead of zeros:
Let's get back to autovacuuming:
As we can see, max_dead_tup has already been fixed. Another thing to pay attention to is that dead_tup = 0. The statistics show that the table does not have dead tuples. and this is true. There is nothing to vacuum in the table yet. Any table used exclusively in append-only mode will not be vacuumed and therefore, the visibility map won't be updated for it. But this makes use of index-only scan impossible.
(Next time we will see that vacuuming will sooner or later reach an append-only table, but this will happen too rarely.)
A lesson learned: if index-only scan is critical, it may be required to manually call a vacuum process.
Now let's turn autovacuum off again and update 31 lines, which is one line greater that the threshold.
Now the condition of vacuum triggering is met. Let's turn autovacuum on and after a short pause we will see that the table has been processed:
VACUUM does not block other processes since it works page by page, but it does produce additional load on the system and can considerably affect the performance.
Throttling for VACUUM
To be able to control the vacuum intensity and therefore, its effect on the system, the process alternates work and waiting. The process will do about vacuum_cost_limit conventional units of work and then it will sleep for vacuum_cost_delay ms.
The default settings are vacuum_cost_limit = 200 and vacuum_cost_delay = 0. The last zero actually means that VACUUM does not sleep, so a specific value of vacuum_cost_limitdoes not matter at all. The reasoning behind this is that if an administrator did have to manually launch VACUUM, he is likely to wish vacuuming to be done as fast as possible.
Nevertheless, if we do set the sleeping time, the amount of work specified in vacuum_cost_limit will be composed of the costs of work with pages in the buffer cache. Each page access is estimated as follows:
- If the page is found in the buffer cache, vacuum_cost_page_hit = 1.
- If it was not found, vacuum_cost_page_miss = 10.
- If it was not found and a dirty page had to be additionally evicted from the buffer cache, vacuum_cost_page_dirty = 20.
Throttling for autovacuuming
For vacuum processes, load throttling works the same way as for VACUUM. But for autovacuum processes and manually launched VACUUM to work with different intensity, autovacuum has its own parameters: autovacuum_vacuum_cost_limit and autovacuum_vacuum_cost_delay. If these parameters have the value of -1, the value of vacuum_cost_limit and/or vacuum_cost_delay is used.
By default autovacuum_vacuum_cost_limit = -1 (i. e., the value of vacuum_cost_limit = 200 is used) and autovacuum_vacuum_cost_delay = 20 ms. On modern hardware, autovacuum will be really slow.
In version 12, the value of autovacuum_vacuum_cost_delay is reduced to 2 ms, which can be taken for a more appropriate first approximation.
Besides, we should note that the limit specified by these settings is common for all worker processes. In other words, when the number of simultaneous worker processes is changed, the overall load remains unchanged. So, to increase the autovacuum performance, when adding worker processes, it makes sense to also increase autovacuum_vacuum_cost_limit.
Use of memory and monitoring
Last time we observed how VACUUM used RAM of size maintenance_work_mem to store tid s to be vacuumed.
Autovacuum does absolutely the same. But there can be many simultaneous worker processes if autovacuum_max_workers is set to a large value. Moreover, all the memory is allocated at once rather than as the need arises. Therefore, for a worker process, its own limitation can be set by means of the autovacuum_work_mem parameter. The default value of this parameter is -1, i. e., it is not used.
As already mentioned, VACUUM can also work with a minimum memory size. But if indexes are created on the table, a small value of maintenance_work_mem can entail repeated index scans. The same is true for autovacuum. Ideally, autovacuum_work_mem should have a minimum value such that no repeated scans occur.
We've seen that to monitor VACUUM, the VERBOSE option can be used (which cannot be specified for autovacuum) or the pg_stat_progress_vacuum view (which, however, shows only the current information). Therefore, the main means to monitor autovacuuming is to use the log_autovacuum_min_duration parameter, which outputs the information to the server message log. It is turned off by default (set to -1). It is reasonable to turn this parameter on (with the value of 0, information on all autovacuum runs will be output) and watch the figures.
This is what the output information looks like:
All the necessary information is available here.
To remind you, it often makes sense to lower the threshold for vacuum triggering in order to process less data at a time rather than increase the memory size.
It may also be reasonable to use the above views to monitor the length of the list of tables that require vacuuming. Increase of the list length will indicate that the autovacuum processes lack time to do their job and the settings need to be changed.
Взяв за основу статью Петра Зайцева об узких местах в производительности MySQL (MySQL Performance Bottlenecks), я хочу немного рассказать о PostgreSQL.
В наши дни для работы с PostgreSQL часто используются ORM-фреймворки. Обычно они работают хорошо, но со временем нагрузка увеличивается и возникает необходимость тюнить сервер базы данных. Каким бы надежным ни был PostgreSQL, но и он может тормозить при увеличении трафика.
Есть много способов устранения узких мест в производительности, но в этой статье мы обратим внимание на следующее:
- Параметры сервера
- Управление подключениями
- Настройка автоочистки (autovacuum)
- Дополнительная настройка автоочистки
- Раздувание таблиц (bloat)
- «Горячие точки» в данных
- Сервера приложений
- Репликация
- Серверное окружение
О «категориях» и «потенциальном влиянии»
«Сложность» говорит о том насколько просто реализовать предлагаемое решение. А «потенциальное влияние» дает представление о степени улучшений в производительности системы. Однако в силу возраста системы, ее типа, технического долга и т.п. точное описание сложности и влияния может быть проблематичным. В конце концов, в сложных ситуациях окончательный выбор всегда за вами.
- Сложность
- Низкая
- Средняя
- Высокая
- Низкая-средняя-высокая
Параметры сервера
Сложность: низкая.
Потенциальное влияние: высокое.Еще не так давно были времена, когда актуальные версии postgres могли работать на i386. С тех пор настройки по умолчанию были изменены, но они по-прежнему сконфигурированы на использование наименьшего количества ресурсов.
Эти параметры изменить очень просто и обычно они настраиваются при первоначальной установке. Неправильные значения этих параметров могут привести к высокой загрузке процессора и ввода-вывода:
- Параметр effective_cache_size ~ от 50 до 75%
- Параметр shared_buffers ~ 1/4 – 1/3 объема оперативной памяти
- Параметр work_mem ~ 10МБ
Вычисление значения shared_buffers — интересная головоломка. На нее можно смотреть с двух сторон: если у вас небольшая база данных, то можно установить значение shared_buffers достаточно большим, чтобы вся база данных поместилась в оперативной памяти. С другой стороны, можно настроить загрузку в память только часто используемых таблиц и индексов (вспоминайте правило 80/20). Раньше рекомендовалось устанавливать значение в 1/3 объема оперативной памяти, но со временем, так как объемы памяти росли, оно было уменьшено до 1/4. Если памяти выделено мало, то будет увеличиваться ввод-вывод и нагрузка на процессор. О слишком большом выделении памяти будет свидетельствовать выход на плато загрузки процессора и ввода-вывода.
Еще один фактор, который следует учитывать — это кэш ОС. При достаточном объеме оперативной памяти Linux будет кэшировать таблицы и индексы в памяти и, в зависимости от настроек, может заставить PostgreSQL поверить в то, что он читает данные с диска, а не из оперативной памяти. Одна и та же страница находится и в буфере postgres и в кэше ОС, и это одна из причин не делать shared_buffers очень большим. С помощью расширения pg_buffercache можно посмотреть использование кэша в реальном времени.
Параметр work_mem задает объем памяти, используемый для операций сортировки. Установка слишком низкого значения гарантирует плохую производительность, так как сортировка будет выполняться с использованием временных файлов на диске. С другой стороны, хотя установка большого значения и не влияет на производительность, но при большом количестве подключений есть риск нехватки оперативной памяти. Проанализировав память, используемую всеми запросами и сеансами, можно посчитать необходимое значение.
Используя EXPLAIN ANALYZE можно увидеть, как выполняются операции сортировки, и, изменяя значение для сеанса, определить момент, когда начинается слив на диск.
Можно также использовать бенчмарки системы.
Управление подключениями
Сложность: низкая.
Потенциальное влияние: низкое-среднее-высокоеВысокая нагрузка обычно связана с увеличением сессий клиентов в единицу времени. Слишком большое их количество может блокировать процессы, вызывать задержки или даже приводить к ошибкам.
Простое решение — увеличить максимальное количество одновременных подключений:
Но более эффективный подход — пул соединений. Существует множество решений, но наиболее популярное — pgbouncer. PgBouncer может управлять соединениями, используя один из трёх режимов:
- Пул сеансов (session pooling). Наиболее корректный подход. При подключении клиента ему выдается соединение и остается за ним, пока он не отключится. Когда клиент отключается, подключение возвращается в пул. Это метод по умолчанию.
- Пул транзакций (transaction pooling). Подключение назначается клиенту только на время транзакции. Когда PgBouncer замечает, что транзакция завершена, подключение возвращается в пул.
- Пул операторов (statement pooling). Наиболее агрессивный метод. Подключение к серверу будет возвращаться в пул сразу после завершения запроса. Транзакции с несколькими операторами в этом режиме запрещены, так как они будут прерываться.
Настройка автоочистки (autovacuum)
Сложность: средняя.
Потенциальное влияние: низкое-среднее.Управление параллельным доступом посредством многоверсионности (Multi-Version Concurrency Control) — один из основополагающих принципов, делающих PostgreSQL таким популярным решением среди СУБД. Однако одним из неприятных моментов является то, что для каждой измененной или удаленной записи создаются неиспользуемые копии, от которых в конечном итоге надо избавляться. Неправильно настроенный процесс автоочистки (autovacuum) может снижать производительность. При этом чем сервер загруженнее, тем сильнее проявляется проблема.
Для управления демоном автоочистки используются следующие параметры:
- Параметр autovacuum_max_workers. При наличии большого количества огромных таблиц стоит увеличить количество одновременно работающих процессов автоочистки (по умолчанию три). В идеале должен быть один рабочий процесс на один процессор, но не больше количества процессоров. Слишком большое количество может увеличить нагрузку на процессор. Обычно берется значение между двумя этими числами. Это баланс между максимальной эффективностью автоочистки и общей производительностью системы.
- Параметр maintenance_work_mem. Чем больше значение, тем эффективнее процесс очистки. Имейте в виду, что есть закон убывающей отдачи. Слишком большое значение в лучшем случае станет пустой тратой оперативной памяти, а в худшем может исчерпать всю доступную память.
- Параметр autovacuum_freeze_max_age уменьшает вероятность TXID WRAPAROUND. Чем значение больше, тем реже он запускается, что снижает нагрузку на систему. Но, как и со всеми параметрами автоочистки, упомянутыми выше, есть нюанс. Если сделать задержку слишком большой, то и вы рискуете исчерпать txid, что приведет к принудительному завершению работы сервера в целях защиты целостности данных. Для определения правильного значения необходимо сопоставлять самый большой/старый txid с процессом автоочистки используя pg_stat_activity на предмет WRAPAROUND.
Аналогично вычислению work_mem, это значение можно посчитать арифметически или выполнить бенчмарки для получения оптимальных значений.
Дополнительная настройка автоочистки
Сложность: высокая.
Потенциальное влияние: высокое.Этот метод, из-за его сложности, следует использовать только когда производительность системы уже на грани физических пределов хоста и это действительно стало проблемой.
Runtime-параметры автоочистки настраиваются в postgresql.conf . К сожалению, нет единого универсального решения, которое будет работать в любой высоконагруженной системе.
Параметры хранения для таблиц. Часто в базе данных значительная часть нагрузки ложится только на несколько таблиц. Настройка индивидуальных параметров автоочистки для таблицы — отличный способ не прибегать к ручному запуску VACUUM, который может существенно влиять на систему.
Настроить таблицы можно с помощью команды:
Раздувание таблиц (bloat)
Сложность: низкая.
Потенциальное влияние: среднее-высокое.Со временем производительность системы может ухудшаться из-за неправильных политик очистки, вследствие чрезмерного раздувания (bloat) таблиц. Так что даже настройка демона автоочистки и ручной запуск VACUUM не решает проблему. В этих случаях на помощь приходит расширение pg_repack.
С помощью расширения pg_repack можно перестроить и реорганизовать таблицы и индексы в условиях продакшена
«Горячие точки» в данных
Сложность: высокая.
Потенциальное влияние: низкое-среднее-высокое.Как и в случае с MySQL, избавление PostgreSQL от «горячих точек» зависит от ваших потоков данных и может даже повлечь за собой изменение архитектуры системы.
В первую очередь следует обращать внимание на следующее:
- Индексы. Убедитесь, что для столбцов, по которым осуществляется поиск есть индексы. Можно использовать системные каталоги и представления для мониторинга и проверки, что запросы используют индексы. Для анализа производительности запросов используйте расширения pg_stat_statement и pgbadger.
- Heap Only Tuples (HOT). Индексов может быть и слишком много. Снизить потенциальное раздувание и уменьшить размер таблицы можно, удалив неиспользуемые индексы.
- Секционирование таблиц. Ничто так не влияет на производительность, как огромная таблица, размер которой в несколько раз превышает средний размер других таблиц. Разбивка большой таблицы на более мелкие секции поможет повысить производительность запросов, например, при запросе данных, секционированных по дате. И так как таблица может обрабатываться только одним процессом автоочистки, то разбивка его на множество меньших таблиц позволяет более чем одному процессу автоочистки выполнять автоматическое удаление. Еще одно преимущество секционирования в том, что удаление большого количества строк намного эффективнее и быстрее, чем из единой огромной таблицы.
- Параллельные запросы. Появились в последних версиях postgres. Теперь для выполнения одного запроса может использоваться несколько процессоров, тогда как раньше запрос обрабатывался только одним.
- Денормализация. Можно повысить производительность, объединив столбцы из нескольких таблиц в одну таблицу. Повышение производительности достигается за счет увеличения избыточности данных. Тщательно обдумайте этот вариант, прежде чем его использовать!
Сервера приложений
Сложность: низкая.
Потенциальное влияние: высокое.Избегайте запуска приложений (PHP, Java и Python) и postgres на одном хосте. Относитесь внимательно к приложениям на этих языках, так как они могут потреблять большие объемы оперативной памяти, особенно сборщик мусора, что влечет за собой конкуренцию с системами баз данных за ресурсы и снижение общей производительности.
Репликация
Сложность: низкая.
Потенциальное влияние: высокое.Синхронная и асинхронная репликация. Последние версии postgres поддерживают логическую и потоковую репликацию как в синхронном, так и в асинхронном режимах. Хотя по умолчанию используется асинхронный режим репликации, но необходимо учитывать последствия использования синхронной репликации, особенно в сетях с существенной задержкой.
Серверное окружение
И последнее, но не менее важное — это простое увеличение мощности хоста. Давайте рассмотрим, на что влияет каждый из ресурсов в плане производительности PostgreSQL:
Приветствую тебя, мой юный 1С-ник. Ты, как и я, не любишь 1С и стараешься как можно быстрее и качественнее отвязаться от задач, связанных с этим продуктом, чтобы больше никогда к ним не возвращаться? Настроил — и забыл, это наш подход!
1С тормозит. Корову можно кормить топовыми процессорами, SSD и немеряным количеством оперативки, но гепардом она всё равно не станет. Этому есть несколько причин:
- Транзакционная модель, от этого в финансах не уйти. Транзакция сидит на транзакции и транзакцией погоняет. Опять же, транзакции подразумевают блокировки, пока блокировка не будет снята, объект не станет доступным другим пользователям.
- Доступность среды разработки. Куча разработчиков сидят, что-то там программируют. Бесконечные циклы, утечки памяти, перерасход ресурсов, кривые руки и непонимание того, что они делают. Ладно бы это делалось централизованно, но сколько 1С серверов, столько и разработчиков. Одну и ту же задачу можно решить разными способами, зачастую решение задачи оказывается не самым оптимальным. В итоге мы слышим: "Это железо тормозит!" "Это база тормозит!"
- Временные таблицы. Весь 1С построен на временных таблицах. На каждый чих создаётся временная таблица, с которой проводятся операции, на них даже индексы строятся. И если БД не может правильно обрабатывать временные таблицы, то успеха не будет. Table Scan — не самая быстрая операция.
- Неправильные настройки сервера БД. Кривые настройки — такой же результат.
Сегодня будем настраивать PostgreSQL 11.9 на сервере Windows Server 2019.
Что лучше: MSSQL или PostgreSQL?
Сложно сказать. С одной стороны, крутые исследователи заявляют о том, что правильно настроенный PostgreSQL выигрывает у MSSQL:
И тут я такой: "А если поднять у MSSQL tempdb в RAM диск?" И снова становится непонятно. Но понятно одно, MSSQL стоит денег, а PostgreSQL бесплатный.
Итак, тестовый стенд (или правильнее сказать, реальный?):
- Сервер, виртуальный, операционная система Windows Server 2019 Standard, триальная.
- CPU: 16 ядер
- ОЗУ: 64 ГБ
- Диск SSD, отдельный для БД.
- Размер базы: 50 Гб
- 1С 8.3 и PostgreSQL 11.9-1.1C вместе на одном сервере
- 50 аккаунтов пользователей 1С в настоящее время
По хорошему, мух следует отделять от котлет. И разносить 1С и БД на разные серверы. Однако, на практике, часто бывает иначе. Сервер имеется один, на нём размещают и базу и сервер 1С. И это не просто предположение, вчера привезли новый сервер и поставили задачу: установить Windows, MSSQL и 1С. Всё на одну машину. Но это немного другая история, не связанная с текущей.
Как разделить ресурсы между 1С и PostgreSQL?
Следовательно, для настроек PostgreSQL я исхожу из цифр:
- CPU: 16 ядер
- ОЗУ: 48 ГБ
- Диск: SSD
- Количество пользователей 1С: 100 (с расчётом на будущее)
Далее RAM — это 48 Гб, которые выделены для PostgreSQL.
Полезные ссылки
Настройка PostgreSQL 11.9
Основной файл настроек PostgreSQL — postgresql.conf. Приступим.
Максимальное количество одновременных подключений к БД. Я просто установил в два раза больше, чем текущее количество 1С пользователей. К базе ещё подключается пользователь для мониторинга и администраторы. Если будет не хватать, то можно потом изменить параметры.
Память
Количество памяти, выделенное для кэша страниц. Рекомендуется от 1/8 до 1/4 RAM. Вычисляю: 48 Гб / 4 = 12 Гб.
Лимит памяти для внутренних обслуживающих задач. Рекомендуется 1/4 RAM. Однако, при увеличении больше 2024MB служба PostgreSQL не запускается.
Кэш файловой системы. Планировщик исходя из этого параметра принимает решение об использовании больших индексов (IndexScan), и это хорошо. Рекомендуется RAM - shared_buffers. Вычисляю: 48 Гб - 12 Гб = 36 Гб.
Лимит памяти для обработки одного запроса. При превышении этого объёма сервер начинает использовать временные файлы на диске. Рекомендуется от 1/32 до 1/16 RAM. Однако, при увеличении больше 2024MB служба PostgreSQL не запускается.
Буфер под временные объекты, например, для временных таблиц. Рекомендуется 1/20 RAM. Однако, при увеличении больше 2024MB служба PostgreSQL не запускается.
Процессор
Максимальное число фоновых процессов. Зависит от количества выделенных для PostgreSQL ядер CPU. По калькулятору.
Задаёт максимальное число рабочих процессов, которое система сможет поддерживать для параллельных запросов. Рекомендуют равным max_worker_processes, однако в этом случае какой-то "толстый" запрос может сожрать все потоки и другим не достанется. Использую половину процессоров.
Задаёт максимальное число рабочих процессов, которые могут запускаться одним узлом Gather илиGather Merge. Не более max_parallel_workers, задал по максимуму.
Задаёт максимальное число рабочих процессов, которые могут запускаться одной служебной командой. По калькулятору.
Задаёт максимальное число файлов, которые могут быть одновременно открыты каждым процессом. Значение по умолчанию — 1000 файлов.
Задаёт максимальное число процессов автоочистки (не считая процесс, запускающий автоочистку), которые могут выполняться одновременно. Чем больше запросов записи, тем больше процессов. Если база только для чтения, то достаточно одного процесса.
Если параметр fsync включён, то при выполнении операции COMMIT данные сразу переписываются из кэша операционной системы на диск, тем самым гарантируется целостность данных при возможном аппаратном сбое. При этом снижается производительность операций записи на диск, поскольку при этом не используются возможности отложенной записи данных операционной системы. Данный параметр можно отключать только при наличие аппаратного RAID контроллера с кэшем в режиме write-back и батарейкой для гарантированной записи данных при отключении питания.
Задаёт допустимое число параллельных операций ввода/вывода, которое говорит PostgreSQL о том, сколько операций ввода/вывода могут быть выполнены одновременно. Для магнитных носителей хорошим начальным значением этого параметра будет число отдельных дисков, составляющих массив RAID 0 или RAID 1, в котором размещена база данных. Для RAID 5 следует исключить один диск (как диск с чётностью). У меня один диск, поэтому у меня данный параметр закомментирован.
Метод, который используется для принудительной записи данных на диск. Возможные значения:
- open_datasync – запись данных методом open() с параметром O_DSYNC,
- fdatasync – вызов метода fdatasync() после каждого commit,
- fsync_writethrough – вызывать fsync() после каждого commit игнорирую паралельные процессы,
- fsync – вызов fsync() после каждого commit,
- open_sync – запись данных методом open() с параметром O_SYNC.
Выбор метода зависит от операционной системы под управлением, которой работает PostgreSQL. Для Windows рекомендуется open_datasync. Для Linux — fdatasync.
В версии PostgreSQL 11.9 не используется, поэтому у меня данный параметр закомментирован. Данный параметр определяет количество сегментов (каждый по 16 МБ) лога транзакций между контрольными точками. В зависимости от объема данных установите этот параметр в диапазоне от 12 до 256 сегментов и, если в логе появляются предупреждения (warning) о том, что контрольные точки происходят слишком часто, постепенно увеличивайте его. Можно установить в 32 (если у вас PostgreSQL поддерживает этот параметр) и дальше смотреть предупреждения в логе.
Часть интервала контрольной точки. Рекомендуется максимальное значение 0.9.
PostgreSQL сначала пишет в буферы, а затем эти буферы сбрасываются в WAL файлы на диск. По молчанию 16MB.
Минимальный размер WAL файла. Установил чуть больше, чем предложил калькулятор.
Максимальный размер WAL файла. Рекомендуется от 2 * min_wal_size до 4 * min_wal_size.
Время сна между циклами записи на диск фонового процесса записи. Данный процесс ответственен за синхронизацию страниц, расположенных в shared_buffers с диском. Слишком большое значение этого параметра приведет к возрастанию нагрузки на checkpoint процесс и процессы, обслуживающие сессии (backend). Малое значение приведет к полной загрузке одного из ядер.
Параметры, управляющие интенсивностью записи фонового процесса записи. За один цикл bgwriter записывает не больше, чем было записано в прошлый цикл, умноженное на bgwriter_lru_multiplier, но не больше чем gwriter_lru_maxpages.
Параметры, управляющие интенсивностью записи фонового процесса записи.
Отключаем синхронизацию с диском в момент коммита. Есть риск потери последних нескольких транзакций, но гарантируется целостность базы данных. Значительно увеличивает производительность.
Пауза в микросекундах перед собственно выполнением сохранения WAL.
Минимальное число одновременно открытых транзакций, при котором будет добавляться задержка commit_delay.
Оптимизатор запросов
Количество записей, просматриваемых при сборе статистики по таблицам. Рекомендуется для 1С от 1000 до 10000. Я поставил 300, если будут зависания, параметр можно увеличить.
Задаёт максимальное число элементов в списке FROM, до которого планировщик будет объединять вложенные запросы с внешним запросом. При меньших значениях сокращается время планирования, но план запроса может стать менее эффективным.
Задаёт максимальное количество элементов в списке FROM, до достижения которого планировщик будет сносить в него явные конструкции JOIN (за исключением FULL JOIN). Рекомендуется 1, но сложные запросы с большим количеством соединений и источников данных станут надолго зависать. Поэтому ставлю чуть меньше значения по умолчанию — 6.
Задаёт приблизительную стоимость последовательного чтения одной страницы с диска. Для NVMe дисков рекомендуется 0.1. Для HDD 1.5 - 2.0. Для SSD 1.1 - 1.3. Можно посмотреть характеристики ваших дисков.
Задаёт приблизительную стоимость случайного чтения одной страницы с диска. Рекомендуется ставить чуть больше чем seq_page_cost.
Задаёт приблизительную стоимость обработки оператора или функции при выполнении запроса. Рекомендуется 0.00025.
Типы таблиц, для которых выполняется немедленный анализ:
- all (все),
- persistent (постоянные),
- temporary (временные),
- none (никакие).
При возникновении проблем с производительностью выполнения регламентных операций можно включить сбор статистики для всех таблиц: all.
Минимальное число изменений строк, после которого может начаться немедленный анализ.
Процент от размера таблицы, при котором начинается немедленный анализ.
Минимальный интервал времени между вызовами ANALYZE для отдельной таблицы (в миллисекундах).
online_analyze использует для временных таблиц системную статистику по умолчанию.
plantuner будет обнулять число страниц/кортежей в таблице, которая не содержит никаких блоков в файле.
Отключает использование планов соединения с вложенными циклами.
Отключает использование планов соединения слиянием.
Сбор статистики
Включает сбор статистики активности в базе данных. Этот параметр по умолчанию включён, так как собранная информация требуется автоочистке.
Разрешить использовать символ "\" для экранирования.
Не выдавать предупреждение об использовании символа "\" для экранирования.
Библиотеки, которые будут загружаться при запуске сервера.
Анализ статистики временных таблиц.
PostgreSQL
Этот параметр управляет средним числом блокировок объектов, выделяемым для каждой транзакции.
Шифрование. Если сеть защищена, то отключаем. Если 1С и PostgreSQL находятся на одном сервере — тем более отключаем.
Прошёл месяц
Сначала были какие-то ошибки в логах postgresql, но они были связаны с процессом разработки. Месяц — полёт нормальный.
Читайте также: