Как устранить зависание расчета себестоимости в 1С:ERP на PostgreSQL

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет
← На главную

Проблема зависания процесса «Закрытие месяца» на этапе расчета фактической себестоимости в конфигурации 1С:ERP Управление предприятием 2 является одной из самых сложных при эксплуатации СУБД PostgreSQL. Часто возникает ситуация, когда на MS SQL Server расчет занимает несколько часов, а на PostgreSQL он «висит» сутками или завершается аварийно. В этой статье мы подробно разберем, как локализовать проблемный запрос, почему СУБД ведет себя именно так и как оптимизировать код и настройки сервера для успешного завершения операции.

Анализ проблемы и локализация узкого места

При выполнении этапа №17 (Расчет фактической себестоимости) система формирует сложные графы распределения затрат. Основная нагрузка ложится на процедуру РасчетСебестоимостиКорректировкаСтоимости.РасчетСебестоимостиТоваров. Рассмотрим ситуацию, когда выполнение «замирает» на формировании временной таблицы ВтПеремещенияСписания. Этот запрос объединяет данные из нескольких источников через ОБЪЕДИНИТЬ ВСЕ и выполняет множественные внутренние и левые соединения.

Проанализируем структуру запроса. Основными участниками являются временные таблицы:

Проблема заключается в том, что PostgreSQL, в отличие от MS SQL, крайне чувствителен к актуальности статистики временных таблиц и количеству соединений в одном запросе. Когда в одном пакете соединяются физические таблицы (например, Документ.РаспределениеПрочихЗатрат) и огромные временные таблицы, оптимизатор может выбрать катастрофически неверный план выполнения, такой как Nested Loop (вложенный цикл) вместо Hash Join.

Причина деградации производительности на PostgreSQL

Выясним причину, по которой запрос, работающий на MS SQL за 5 часов, на PostgreSQL может выполняться бесконечно. Основные факторы:

  1. Соединение по полям типа Ссылка: В PostgreSQL ссылки 1С хранятся как UUID. Если СУБД не может правильно оценить кардинальность (количество уникальных значений) во временной таблице, она начинает перебирать каждую запись физической таблицы документа для каждой строки временной таблицы.
  2. Ограничения планировщика: Параметры from_collapse_limit и join_collapse_limit в стандартных настройках PostgreSQL позволяют оптимизатору перестраивать порядок соединений. В сложных запросах ERP это приводит к тому, что СУБД «запутывается» и выбирает самый долгий путь.
  3. Нехватка оперативной памяти: Если объем данных во временных таблицах превышает выделенный work_mem, СУБД начинает сбрасывать промежуточные результаты на диск (temp_files), что замедляет процесс в десятки раз.

Способ 1: Оптимизация текста запроса (Разбиение и упрощение)

Наиболее эффективным методом решения, найденным на практике, является «разрезание» одного огромного запроса на несколько более простых. Это помогает PostgreSQL строить предсказуемые планы выполнения. Рассмотрим пример оптимизации проблемного участка, где происходит соединение с документом РаспределениеПрочихЗатрат.

Проанализируем исходный код, который вызывает зависание:


ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РаспределениеПрочихЗатрат КАК Реквизиты 
ПО Расходы.Регистратор = Реквизиты.Ссылка 
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтУзлыКорректировки КАК УзлыКорректировкиИсточник 
ПО (УзлыКорректировкиИсточник.Организация = Расходы.Организация) 
И (УзлыКорректировкиИсточник.АналитикаФинансовогоУчета = Реквизиты.Подразделение)

Для оптимизации рекомендуется предварительно выгрузить необходимые реквизиты документов во временную таблицу, проиндексировать её и только потом соединять с основными данными. Это избавляет СУБД от необходимости обращаться к «тяжелой» физической таблице документов внутри сложного цикла. Если же реквизиты (например, Подразделение) уже есть в исходной таблице Расходы, соединение с документом можно полностью исключить, как это сделано в успешном кейсе:


// Пример оптимизированного фрагмента без лишнего соединения с документом
ВЫБРАТЬ 
    УзлыКорректировкиИсточник.НомерУзла, 
    УзлыКорректировкиПриемник.НомерУзла, 
    Расходы.ПоказательОтнесенияНаПартию, 
    Статьи.ХарактерПроизводственныхЗатрат
ИЗ втПрочиеРасходыНезавершенногоПроизводства КАК Расходы 
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.СтатьиРасходов КАК Статьи 
ПО Расходы.СтатьяРасходов = Статьи.Ссылка 
// Соединение с Документ.РаспределениеПрочихЗатрат удалено, 
// так как нужные данные уже есть во временной таблице или могут быть получены иначе
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтУзлыКорректировки КАК УзлыКорректировкиИсточник 
ПО (УзлыКорректировкиИсточник.Организация = Расходы.Организация) 
И (УзлыКорректировкиИсточник.СтатьяРасходов = Расходы.СтатьяРасходов)

Способ 2: Использование функции ВЫРАЗИТЬ для типизации ссылок

Если в запросе используются соединения по полю Регистратор или другим составным типам, PostgreSQL может не использовать индексы. Чтобы помочь СУБД, используем типизацию через ВЫРАЗИТЬ. Это особенно актуально, если в регистре накопления много видов документов-регистраторов, но в конкретном периоде расчет идет только по нескольким.

Пример применения:


ВЫБРАТЬ 
    Таб.Регистратор,
    ВЫРАЗИТЬ(Таб.Регистратор КАК Документ.ПриобретениеТоваровУслуг) КАК КонкретныйДокумент
ИЗ РегистрНакопления.СебестоимостьТоваров КАК Таб
ГДЕ Таб.Регистратор ССЫЛКА Документ.ПриобретениеТоваровУслуг

Способ 3: Настройка параметров СУБД и инфраструктуры

Посмотрим на настройки сервера. Для базы объемом около 100 ГБ и 25 пользователей конфигурация 32 ГБ ОЗУ является пограничной, особенно если сервер 1С и СУБД совмещены на одной физической машине (Windows Server 2008). Проанализируем ключевые параметры в postgresql.conf:

Важное замечание по ОС: Windows Server 2008 имеет устаревшие механизмы кэширования. Если есть возможность, перенесите СУБД на Linux (например, Ubuntu или CentOS) — PostgreSQL работает с памятью в этих системах гораздо эффективнее, что критично для тяжелых запросов 1С.

Рекомендации по обслуживанию базы данных

Перед запуском закрытия месяца обязательно выполните следующие действия:

  1. Обновите статистику всей базы данных (команда ANALYZE).
  2. Очистите процедурный кэш сервера 1С (перезапуск службы или использование специальных скриптов).
  3. Проверьте наличие свободного места на дисках, где располагаются временные файлы СУБД.
  4. В настройках закрытия месяца (раздел «Ограничения на размер различных структур данных») попробуйте увеличить «Максимальную длину цепочки движения партий» до 1500 или более, если у вас сложное многопередельное производство.

Подводя итог, отметим: если расчет «зависает» на конкретном запросе, проанализируйте возможность его упрощения в расширении или через патчи от 1С. PostgreSQL — мощная система, но она требует более тонкой настройки и чистоты кода запросов по сравнению с MS SQL.

← На главную