Почему PostgreSQL в 1С работает медленнее MS SQL и как его оптимизировать?

Системный администратор 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При первичном тестировании информационной базы 1С на PostgreSQL администраторы и разработчики часто сталкиваются с ситуацией, когда одинаковый тяжелый запрос или отчет выполняется в несколько раз медленнее, чем на MS SQL Server (например, 65 секунд против 15 секунд). Разберем причины такого поведения СУБД и рассмотрим комплекс мер по тонкой настройке конфигурации для достижения максимальной производительности.

1. Анализ причин низкой производительности «из коробки»

Выделим основные факторы, которые приводят к существенной разнице во времени выполнения запросов между MS SQL и PostgreSQL:

  1. Неоптимальные параметры СУБД по умолчанию: Стандартный конфигурационный файл postgresql.conf ориентирован на запуск СУБД с минимальным потреблением ресурсов практически на любом оборудовании. Без ручной настройки СУБД выделяет критически мало памяти под кэш и операции сортировки.
  2. Конфликт ресурсов при одновременной работе служб: Если для сравнительного теста на одном сервере запущены и MS SQL, и PostgreSQL, служба MS SQL по умолчанию захватывает всю доступную оперативную память, оставляя PostgreSQL работать в условиях жесткого дефицита ОЗУ.
  3. Холодный кэш против прогретого: На боевой базе MS SQL с работающими пользователями необходимые страницы данных уже находятся в оперативной памяти («горячий кэш»). На только что развернутом PostgreSQL тестовый запрос вынужден считывать все данные с диска («холодный кэш»).
  4. Отсутствие актуальной статистики: После выгрузки и загрузки базы через .dt оптимизатор PostgreSQL не имеет распределения данных по таблицам и индексам, из-за чего строит наихудшие планы выполнения (например, полное сканирование Seq Scan вместо индексного поиска).
  5. Особенности операционной системы Windows: Архитектура PostgreSQL исторически создавалась для UNIX-систем. В среде Windows работа с памятью и управление процессами обладают дополнительными накладными расходами.
  6. Специфика выполнения вложенных условий и RLS: Механизмы разделения прав на уровне записей (RLS) в типовых конфигурациях (УТ, КА, ERP) формируют сложные конструкции с предикатом EXISTS, которые планировщик PostgreSQL без дополнительной оптимизации обрабатывает медленнее, чем MS SQL.

2. Первичная инициализация базы и сбор статистики

Проанализируем обязательный шаг, без которого любые тесты производительности будут некорректными. Сразу после загрузки информационной базы необходимо принудительно запустить сбор статистики для всех таблиц СУБД.

Выполним сбор статистики через командную строку или консоль управления СУБД:

VACUUM FULL ANALYZE;

В дальнейшем сбор статистики и очистку устаревших версий строк должен поддерживать механизм автовакуума. Для конфигураций 1С с интенсивной записью изменим пороги срабатывания в файле postgresql.conf:


autovacuum = on
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
autovacuum_max_workers = 4

3. Тонкая настройка конфигурации PostgreSQL под 1С

Разберем ключевые параметры postgresql.conf, влияющие на скорость выполнения запросов и работу с памятью:

  1. Память для кэширования таблиц (shared_buffers): Задает объем памяти, используемый PostgreSQL для кэширования данных. Рекомендуется выделять около 25% от всей физической оперативной памяти сервера (например, 8GB при общем объеме 32GB).
  2. Оценка дискового кэша ОС (effective_cache_size): Подсказывает планировщику, сколько памяти доступно в дисковом кэше операционной системы. Устанавливается на уровне 50–75% от общего объема ОЗУ (например, 16–24GB для сервера с 32GB).
  3. Память на операции сортировки и хеширования (work_mem): Выделяется под каждую операцию внутри запроса. При низких значениях промежуточные данные сбрасываются во временные файлы на диск. Для 1С рекомендуется задавать диапазон от 32MB до 128MB в зависимости от сложности отчетов.
  4. Буферы временных таблиц (temp_buffers): Платформа 1С активно использует временные таблицы в пакетных запросах. Увеличение параметра до 128MB–256MB позволяет обрабатывать их в ОЗУ без лишней нагрузки на дисковую подсистему.
  5. Стоимость случайного чтения (random_page_cost): Значение по умолчанию 4.0 рассчитано на медленные HDD. Для быстрых SSD и NVMe-накопителей параметр обязательно уменьшают до 1.1–1.5, чтобы планировщик активнее задействовал индексный доступ вместо полного сканирования.
  6. Лимиты сворачивания соединений (join_collapse_limit и from_collapse_limit): Для предотвращения построения неоптимальных планов в громоздких запросах 1С эти параметры устанавливают равными 8.

Пример блока настроек для сервера с 32 GB ОЗУ и SSD-дисками:


shared_buffers = 8GB
effective_cache_size = 24GB
work_mem = 64MB
maintenance_work_mem = 1GB
temp_buffers = 128MB
random_page_cost = 1.2
join_collapse_limit = 8
from_collapse_limit = 8
max_locks_per_transaction = 256

4. Оптимизация операционной системы Linux

Для достижения максимального быстродействия СУБД рекомендуется переносить PostgreSQL на выделенный сервер под управлением Linux. Рассмотрим базовые параметры тюнинга ядра ОС:

  1. Отключение Transparent Huge Pages (THP): Механизм прозрачных больших страниц вызывает задержки при активном выделении памяти. Переведем его в режим never:
    
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
    
  2. Ограничение сброса страниц в Swap (vm.swappiness): Установим значение в sysctl.conf на уровень 1–10, чтобы ОС не выгружала кэш СУБД на диск:
    
    vm.swappiness = 1
    vm.overcommit_memory = 2
    vm.overcommit_ratio = 80
    
  3. Настройка монтирования файловой системы: При монтировании разделов с базами данных (ext4 или XFS) используем опцию noatime, чтобы исключить постоянную запись времени доступа к файлам.

5. Особенности кода запросов 1С при работе с PostgreSQL

Если оптимизация конфигурации выполнена, но конкретный отчет или алгоритм продолжает работать медленно, проанализируем структуру запроса в 1С:

  1. Замена левых соединений с подзапросами на временные таблицы: PostgreSQL хуже справляется с разворачиванием вложенных выборок в секции СОЕДИНЕНИЕ. Перенесем вложенный запрос в отдельную секцию МенеджерВременныхТаблиц с обязательным созданием индексов:
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
    |	ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток
    |ПОМЕСТИТЬ ВТ_Остатки
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
    |
    |ИНДЕКСИРОВАТЬ ПО
    |	Номенклатура
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	ЕСТЬNULL(ВТ_Остатки.Остаток, 0) КАК Остаток
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Остатки КАК ВТ_Остатки
    |		ПО Номенклатура.Ссылка = ВТ_Остатки.Номенклатура";
    
  2. Индексация временных таблиц: Поля, по которым выполняется условие соединения или фильтрация (ГДЕ), обязательно указываем в секции ИНДЕКСИРОВАТЬ ПО. Без индекса СУБД выполняет полное сканирование временной таблицы.
  3. Сопоставление типов данных: Исключим сравнение строк разной фиксированной длины и соединение по разнотипным полям, так как это блокирует использование стандартных индексов.
← На главную