Нам часто приходится сталкиваться с задачами, требующими оптимизации производительности информационных систем. Однако иногда возникает прямо противоположная, но не менее интересная задача — искусственно замедлить работу определенной базы данных. Рассмотрим подробно, как мы можем добиться заметного торможения базы 1С, размещенной на отдельном инстансе PostgreSQL, используя различные настройки СУБД и операционной системы.
postgresql.conf)Основной инструмент для настройки производительности PostgreSQL – это файл postgresql.conf. Путем изменения ключевых параметров мы можем существенно повлиять на скорость работы базы. Важно помнить, что мы настраиваем отдельный инстанс PostgreSQL, поэтому изменения не затронут другие базы в кластере.
Ограничение использования оперативной памяти: Уменьшение буферов и рабочей памяти заставит PostgreSQL чаще обращаться к диску, что при ограниченных ресурсах значительно замедлит работу.
<strong>shared_buffers</strong> = 16MB: Устанавливаем очень низкое значение для разделяемых буферов. Это приведет к тому, что PostgreSQL будет кэшировать меньше данных в памяти, увеличивая число дисковых операций.<strong>work_mem</strong> = 1MB: Уменьшаем максимальный объем памяти, который может быть использован внутренней операцией сортировки или хеширования перед записью во временные файлы на диск. При больших объемах данных это гарантированно приведет к сбросу на диск и замедлению.<strong>maintenance_work_mem</strong> = 32MB: Этот параметр влияет на операции, связанные с обслуживанием базы (например, VACUUM, CREATE INDEX). Низкое значение замедлит их, косвенно влияя на производительность запросов.<strong>effective_cache_size</strong>: Установим его на очень низкое значение, даже ниже физической памяти сервера. Это заставит PostgreSQL меньше полагаться на кэширование данных в оперативной памяти и чаще обращаться к диску.<strong>temp_buffers</strong>: Если установить его на очень низкое значение, то операции, требующие временных файлов (например, сложные сортировки или агрегации), будут чаще использовать диск вместо оперативной памяти, что при медленном диске приведет к сильному замедлению.Отключение параллельных операций: Современные версии PostgreSQL активно используют параллельные запросы. Их отключение приведет к выполнению многих операций в одном потоке, что замедлит обработку больших объемов данных.
<strong>max_parallel_workers_per_gather</strong> = 0: Запрещаем использование параллельных рабочих процессов для отдельных узлов плана запроса.<strong>max_parallel_workers</strong> = 0: Полностью отключаем параллельные рабочие процессы.<strong>max_parallel_maintenance_workers</strong> = 0: Отключаем параллельные рабочие процессы для операций обслуживания.<strong>jit</strong> = off: Отключаем JIT-компиляцию (Just-In-Time) запросов, которая может ускорять выполнение сложных запросов.<strong>aqo.enabled</strong> = off: Если используется расширение AQO (Automatic Query Optimization), его отключение может привести к выбору менее оптимальных планов.Параметры WAL (журнала предзаписи): Настройка WAL может повлиять на частоту операций записи на диск и, как следствие, на производительность.
<strong>max_wal_size</strong> = 100MB<strong>min_wal_size</strong> = 80MB<strong>checkpoint_timeout</strong> = 30min<strong>checkpoint_completion_target</strong> = 0.5: Эти параметры могут быть настроены таким образом, чтобы контрольные точки срабатывали чаще или требовали больше ресурсов.Настройки коммитов и записи на диск:
<strong>synchronous_commit</strong> = on: Включение синхронных коммитов гарантирует, что транзакция будет зафиксирована на диске до того, как клиенту будет отправлено подтверждение, что увеличивает задержку.<strong>fsync</strong> = on<strong>full_page_writes</strong> = on: Эти параметры обеспечивают целостность данных, но могут увеличивать нагрузку на диск. Оставляем их включенными, так как их отключение небезопасно.Ограничение подключений:
<strong>max_connections</strong> = 10: Сильное ограничение числа одновременных подключений может привести к задержкам при попытке установить новое соединение с базой.Манипуляции с планировщиком запросов: Планировщик PostgreSQL выбирает наиболее эффективный способ выполнения запроса. Мы можем обмануть его, чтобы он выбирал неоптимальные планы.
Отключение методов планировщика: Мы можем выборочно отключать определенные типы планов, заставляя планировщик использовать менее эффективные.
SET enable_nestloop = off;
SET enable_mergejoin = off;
SET enable_hashjoin = off;
SET enable_indexscan = off;
SET enable_indexonlyscan = off;
SET enable_bitmapscan = off;
SET enable_sort = off;
Если мы оставим включенным только enable_seqscan = on, большинство запросов будут выполнять последовательное сканирование таблиц, что будет чрезвычайно медленно даже на небольших объемах данных.
Искусственное увеличение стоимости операций: Планировщик использует "стоимости" для оценки различных шагов запроса. Мы можем искусственно завысить эти стоимости, чтобы неоптимальные планы стали "дешевле" для планировщика.
<strong>seq_page_cost</strong>: Стоимость последовательного чтения одной страницы. Увеличиваем до очень больших значений (например, 1000.0 или 10000.0).<strong>random_page_cost</strong>: Стоимость случайного чтения одной страницы. Увеличиваем до очень больших значений (например, 10000.0 или 100000.0). Это заставит планировщик избегать использования индексов.<strong>cpu_tuple_cost</strong>: Стоимость обработки одной строки процессором. Увеличиваем (например, 1.0).<strong>cpu_index_tuple_cost</strong>: Стоимость обработки одной строки индекса процессором. Увеличиваем (например, 0.5).<strong>geqo_threshold</strong>: Порог, при котором используется генетический планировщик (GEQO). Установим его на низкое значение (например, 2), чтобы GEQO всегда использовался, даже для простых запросов, что может замедлить их планирование.geqo_effort, geqo_pool_size, geqo_generations, geqo_selection_bias, geqo_seed) также могут быть изменены для еще большего замедления планирования.<strong>plan_cache_mode = force_generic_plan</strong>: Заставляет планировщик использовать более общие, но часто менее эффективные планы запросов, которые кэшируются.Параметры Autovacuum: Автовакуум поддерживает чистоту базы, но неправильная его настройка может снизить производительность.
<strong>autovacuum_vacuum_cost_delay</strong>: Установим на очень большое значение (например, 1000ms). Это заставит автовакуум работать крайне медленно, "съедая" ресурсы диска и CPU в фоновом режиме, замедляя выполнение обычных запросов.<strong>autovacuum_vacuum_scale_factor</strong> и <strong>autovacuum_analyze_scale_factor</strong>: Уменьшим до минимальных значений (например, 0.01). Это приведет к тому, что автовакуум будет запускаться гораздо чаще, но при этом работать неэффективно из-за других ограничений, постоянно конкурируя за ресурсы с пользовательскими запросами.Если настроек PostgreSQL недостаточно, мы можем ограничить ресурсы для процесса конкретного инстанса PostgreSQL на уровне операционной системы.
Ограничение CPU и памяти:
systemd cgroups: Если ваш инстанс PostgreSQL запускается через systemd, мы можем использовать cgroups для наложения жестких лимитов на его потребление CPU и памяти. Для этого мы отредактируем юнит-файл сервиса (например, postgrespro-1c-17-pg1-slow.service).
[Service]
...
CPUAim=1000 # 1% CPU (1000/100000, где 100000 - это 100% CPU)
MemoryMax=64M # Максимальный объем памяти в 64MB
После изменения юнит-файла необходимо перезагрузить сервис: sudo systemctl daemon-reload && sudo systemctl restart postgrespro-1c-17-pg1-slow.service.
Docker: Если инстанс запущен в Docker, мы можем легко ограничить ресурсы контейнера.
docker run --cpus="0.1" --memory="64m" ...
Здесь --cpus="0.1" выделяет 10% одного CPU, а --memory="64m" ограничивает память 64 мегабайтами.
Ограничение I/O (ввода/вывода): Ограничение пропускной способности диска будет одним из самых эффективных способов замедления.
systemd I/O BandwidthMax: Для сервиса PostgreSQL мы можем установить лимиты на чтение/запись с диска.
sudo systemctl set-property postgrespro-1c-17-pg1-slow.service IOWriteBandwidthMax="/dev/nvme0n1p1 100K"
sudo systemctl set-property postgrespro-1c-17-pg1-slow.service IOReadBandwidthMax="/dev/nvme0n1p1 100K"
Здесь /dev/nvme0n1p1 – это путь к диску (замените на ваш реальный путь), а 100K – лимит в 100 килобайт в секунду, что очень мало для NVMe диска.
ionice: Мы можем изменить приоритет доступа к диску для процесса PostgreSQL, сделав его очень низким.
ionice -c idle -p <PID_процесса_postgres>
Это заставит процесс использовать диск только тогда, когда другие процессы не нуждаются в нем, что значительно замедлит I/O.
Симуляция медленного диска с fio: Хотя это непрямой способ, мы можем запустить отдельный процесс fio, который будет интенсивно нагружать диск с заданными параметрами задержки, тем самым косвенно замедляя PostgreSQL.
Приоритет процессов (nice): Изменение приоритета с помощью nice делает процесс менее приоритетным для планировщика CPU. Однако это не ограничивает ресурсы напрямую, а лишь уменьшает вероятность его выполнения, когда есть другие конкурирующие задачи.
nice -n 19 <команда_запуска_postgres>
Это может дать небольшой эффект, но для сильного замедления необходимы более жесткие ограничения.
Индексы значительно ускоряют выборку данных. Если мы хотим замедлить базу, мы можем их удалить или сделать неэффективными.
Удаление индексов: Самый радикальный способ – удалить некластеризованные индексы. Это заставит PostgreSQL выполнять полные сканирования таблиц для большинства запросов, которые ранее использовали индексы.
Для PostgreSQL это можно сделать следующим образом:
DROP INDEX index_name;
Для получения списка индексов мы можем использовать системные каталоги PostgreSQL.
Пересоздание индексов с низким fillfactor: Мы можем пересоздать индексы с очень низким параметром fillfactor, что приведет к созданию менее плотных индексов, занимающих больше места и требующих больше операций ввода/вывода для чтения.
Если взаимодействие между сервером 1С и PostgreSQL происходит по сети, мы можем искусственно внести задержки в сетевой трафик для конкретного инстанса.
Использование netem: Утилита netem (Network Emulator) в Linux позволяет добавлять задержки, потери пакетов или дублирование пакетов для сетевого интерфейса.
sudo tc qdisc add dev eth0 root netem delay 500ms 100ms
sudo tc qdisc add dev eth0 root netem loss 10%
Первая команда добавит задержку в 500 мс с разбросом в 100 мс для всех пакетов на интерфейсе eth0. Вторая – добавит 10% потерь пакетов. Это будет имитировать очень плохую сетевую связь, что напрямую повлияет на скорость обмена данными.
В крайнем случае, если это возможно по условиям задачи, развертывание более старой и менее оптимизированной версии PostgreSQL для замедляемой базы может само по себе привести к снижению производительности, так как старые версии могут не иметь многих современных оптимизаций.
Применяя комбинацию этих методов, мы сможем добиться заметного и ощутимого замедления работы нужной базы 1С на отдельном инстансе PostgreSQL, продемонстрировав необходимость в дальнейшем анализе или изменении подходов к ресурсам.