Как ускорить этап «Партионный учет: ПодготовкаДанныхДляУчетаНДСиУСН2_4» при расчете себестоимости в 1С:ERP?

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

При закрытии месяца в программе «1С:ERP Управление предприятием» одной из наиболее ресурсоемких операций традиционно является расчет себестоимости. Проводя детальный анализ протокола закрытия месяца, многие специалисты сталкиваются с тем, что львиную долю времени занимает этап Партионный учет: ПодготовкаДанныхДляУчетаНДСиУСН2_4. Данная операция может выполняться часами, парализуя работу СУБД и сервера приложений, даже когда объем обрабатываемых данных кажется незначительным.

В этой статье мы подробно разберем, почему возникает данная проблема, рассмотрим технические и методологические способы ее решения, а также научимся оптимизировать систему для быстрого и стабильного расчета партий.

Технические причины медленной работы алгоритма

Для начала выясним причину, почему именно этот этап вызывает такие задержки. В отличие от стандартного расчета распределения затрат, расчет партионного учета для целей НДС и УСН строит сложнейший направленный граф движения запасов. Этот граф состоит из узлов (партий поступления, выпусков, полуфабрикатов) и дуг (перемещений, списаний, реализаций). Алгоритм пытается проследить полную цепочку движения каждой единицы номенклатуры от момента ее закупки или выпуска до конечного выбытия.

Основные технические проблемы, с которыми сталкивается система в процессе этого расчета, можно разделить на следующие категории:

  1. Эскалация блокировок при записи в СУБД. Результаты расчета записываются в регистр сведений ДетализацияПартийТоваровДляНДСиУСН2_4. Когда база данных пытается одновременно записать сотни тысяч строк, СУБД (MS SQL или PostgreSQL) накладывает монопольные блокировки на таблицы. Это приводит к резкому падению производительности и зависанию рабочих процессов rphost.
  2. Сравнение больших наборов данных в оперативной памяти. Перед записью новых движений система по умолчанию пытается сравнить существующие в базе записи с новыми расчетными данными, чтобы перезаписать только изменившиеся строки. При миллионных объемах записей это сравнение перегружает оперативную память сервера приложений и может приводить к аварийному завершению работы фонового задания расчета себестоимости по таймауту.
  3. Бесконечные циклы в графе затрат. Если в учете присутствуют так называемые петли или встречный выпуск (например, когда полуфабрикат А используется для производства продукции Б, а продукция Б в этом же месяце прямо или косвенно списывается на расходы по производству А), алгоритм распределения начинает бесконечно перебирать варианты. Количество итераций обхода графа растет лавинообразно, что выливается в многочасовое ожидание завершения этапа.

Способ 1. Принудительное очищение старых движений (Программный обход)

Рассмотрим по шагам один из наиболее эффективных технических приемов, который позволяет существенно ускорить запись движений в регистры. Как показывает практика, значительное ускорение дает принудительная очистка старых записей перед расчетом, что избавляет систему от тяжелой операции сравнения наборов данных в памяти.

Для реализации этого метода мы можем использовать механизм расширений конфигурации. Нам необходимо переопределить поведение в процедуре ИнициализироватьОбслуживаемыеРегистры и установить флаг принудительной очистки в параметрах расчета.

Разберем по шагам, как это сделать:

  1. Создадим новое расширение конфигурации в режиме «1С:Предприятие - Конфигуратор».
  2. Найдем общий модуль или модуль менеджера, в котором расположена процедура ИнициализироватьОбслуживаемыеРегистры, и добавим ее в расширение с методом переопределения (аннотация &После).
  3. Внедрим код, который принудительно устанавливает признак очистки старых движений в истину.

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


&После("ИнициализироватьОбслуживаемыеРегистры")
Процедура Расш1_ИнициализироватьОбслуживаемыеРегистры(ПараметрыРасчета, Регистры)
    
    // Устанавливаем флаг принудительной очистки старых движений, 
    // чтобы избежать тяжелой процедуры сравнения наборов записей в памяти
    Если ПараметрыРасчета.Свойство("Отладка") Тогда
        ПараметрыРасчета.Отладка.Вставить("ОчищатьСтарыеДвижения", Истина);
    Иначе
        СтруктураОтладки = Новый Структура;
        СтруктураОтладки.Вставить("ОчищатьСтарыеДвижения", Истина);
        ПараметрыРасчета.Вставить("Отладка", СтруктураОтладки);
    КонецЕсли;
    
КонецПроцедуры

Установка параметра ОчищатьСтарыеДвижения в значение Истина заставляет платформу просто очистить старые движения по регистру ДетализацияПартийТоваровДляНДСиУСН2_4 перед записью новых. Это полностью исключает этап сравнения «было / стало» на сервере приложений 1С и позволяет СУБД выполнить прямую быструю вставку данных, сокращая время выполнения этапа в несколько раз.

Способ 2. Оптимизация структуры документов выпуска и распределения затрат

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

При таком подходе в графе расчета партий создается гигантский, неделимый узел. Алгоритм не может рассчитать его по частям или распределить на несколько потоков. Чтобы исправить эту ситуацию, проанализируем структуру табличной части ВыходныеИзделия документа Производство без заказа.

В этой табличной части присутствует важный реквизит — НомерГруппыЗатрат. Если вся выпущенная продукция в документе является однотипной и распределение затрат идет по долям стоимости, система по умолчанию проставляет всем строкам НомерГруппыЗатрат = 1. В результате формируется всего одна неделимая партия производства с одним основным изделием.

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

  1. Дробление документов выпуска. Избегайте создания «документов-гигантов». Гораздо эффективнее распределить выпуск по отдельным документам Производство без заказа — например, создавать их под конкретные производственные смены, склады выпуска или группы однородной номенклатуры.
  2. Управление группами затрат. Если необходимо выпустить разнородную продукцию в рамках одного документа, мы можем программно (через подписку на событие) или вручную присваивать уникальный НомерГруппыЗатрат разным строкам табличной части ВыходныеИзделия. Это приведет к тому, что при проведении документа сформируется множество отдельных партий продукции, которые система сможет рассчитать параллельно и значительно быстрее.
  3. Отказ от сложных распределений внутри выпуска. Вместо того чтобы списывать материалы непосредственно в документ выпуска на общую кучу, целесообразно использовать схему распределения через статьи расходов. Материалы списываются документом Внутреннее потребление товаров (с видом операции Списание на расходы) на определенную статью затрат. Затем эта статья распределяется по настроенным правилам на партии производства по долям стоимости или иным базам распределения. Это существенно упрощает граф партионного учета для целей НДС и УСН.

Способ 3. Настройка параметров закрытия месяца

Давайте разберем, какие встроенные инструменты оптимизации предоставляет сама система «1С:ERP». Начиная с версий линейки 2.4, разработчики добавили ряд важных параметров, управляющих расчетом партий.

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

  1. Перейдем в рабочее место Закрытие месяца.
  2. Откроем меню Настройки и выберем пункт Настройка параметров операций закрытия месяца... (обратите внимание, что в некоторых версиях конфигурации этот пункт становится видимым только после включения режима отладки расчета себестоимости).
  3. Настроим параметр Максимальная порция выборки данных при расчете партии. Рекомендуется установить значение в диапазоне от 10 000 до 20 000. Это заставит систему разбивать огромный граф на мелкие, легко обрабатываемые СУБД порции данных.
  4. Настроим параметр Максимальное количество движений в порции данных для записи. Ограничение этого объема предотвратит эскалацию блокировок таблиц на уровне базы данных SQL.
  5. Зададим оптимальное количество потоков в параметре Максимальное количество одновременно выполняемых потоков расчета партий. Для серверов с высокой производительностью рекомендуется устанавливать значение, равное количеству физических ядер процессора за вычетом 2-4 ядер, зарезервированных для текущей работы пользователей. Многопоточный расчет позволяет параллельно обрабатывать независимые ветки графа партий.

Также обязательно убедитесь в том, что в системе корректно установлены цены номенклатуры с типом «Плановая стоимость» для всех позиций, участвующих в выпуске и сборке. При отсутствии плановых цен алгоритм подготовки данных для НДС вынужден выполнять тяжелые дополнительные запросы к СУБД для поиска альтернативных стоимостных оценок, что в разы замедляет расчет.

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

← На главную