Как ускорить расчет себестоимости в 1С:УПП на крупных базах данных?

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

Рано или поздно крупное производственное предприятие, работающее на платформе 1С:Управление производственным предприятием (УПП), сталкивается с проблемой катастрофического замедления процедуры закрытия месяца. Процесс, который ранее занимал несколько часов и успешно завершался за ночь, внезапно начинает выполняться 20–22 часа или вообще зависает. В условиях непрерывного производства, когда завод работает без выходных, такая задержка парализует получение оперативной управленческой и финансовой отчетности.

В этой статье мы подробно разберем, почему происходит резкое падение производительности при расчете себестоимости в 1С:УПП, и рассмотрим комплекс мер по оптимизации программной логики 1С и настроек СУБД Microsoft SQL Server.

---

Шаг 1. Первичная диагностика: РАУЗ или Партионный учет?

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

  1. Расширенная аналитика учета затрат (РАУЗ) — наиболее частый выбор для крупных баз. Расчет себестоимости в этом режиме строится на решении систем линейных алгебраических уравнений (СЛАУ) итерационным методом Якоби. Основное узкое место здесь — математическая сходимость матрицы уравнений.
  2. Традиционный партионный учет — расчет строится на последовательном списании партий по методам FIFO/LIFO или по средней стоимости. Основное узкое место здесь — последовательное проведение ресурсоемких документов, корректировки стоимости и распределение косвенных расходов по сложным алгоритмам.

Проанализируем детально методы ускорения для каждого из этих режимов.

---

Шаг 2. Оптимизация расчета при использовании РАУЗ

Если на предприятии включен РАУЗ, то расчет себестоимости пытается решить гигантское математическое уравнение. Если в уравнениях появляются противоречивые данные, система начинает бесконечно циклиться, что лавинообразно увеличивает время расчета.

1. Устранение «мертвых петель» и встречного выпуска

Встречный выпуск возникает, когда продукция, выпущенная в текущем месяце, прямо или косвенно списывается на затраты собственного производства (например, Товар А участвует в производстве Полуфабриката Б, а Полуфабрикат Б списывается на выпуск Товара А). Математический аппарат РАУЗ пытается решить это циклическое уравнение итерациями. По умолчанию лимит итераций равен 50. Если система не может найти сходимость, она выполняет все 50 тяжелых математических циклов для каждой позиции.

Что делать:

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

2. Контроль отрицательных остатков в НЗП

Наличие отрицательных остатков по количеству или стоимости на регистрах учета затрат (например, УчетЗатратРегл или УчетЗатрат) приводит к тому, что норма матрицы СЛАУ становится больше единицы. Математический алгоритм РАУЗ начинает «расходиться», бесконечно накапливая погрешность, и считает себестоимость часами.

Что делать: перед запуском расчета себестоимости обязательно сформируем отчет «Ведомость по учету затрат» и полностью устраним все отрицательные остатки как по количеству, так и по стоимости.

3. Оптимизация структуры регистра «АналитикаУчетаПартий»

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

Что делать: привлечем программиста 1С для оптимизации структуры регистра в конфигураторе. Перенесем наиболее заполненные измерения (Номенклатура, Склад, ХарактеристикаНоменклатуры) в самое начало списка измерений регистра сведений, а пустые или редко используемые сдвинем в конец. Также рекомендуется установить свойство «Индексировать» для часто используемых аналитик.

4. Отключение использования временных таблиц для расчета СЛУ

В документе «Установка параметров учета» или в настройках закрытия месяца присутствует флаг ИспользоватьВременныеТаблицыДляРасчетаСЛУ. На очень больших базах данных СУБД из-за особенностей округления и построения планов запросов может зависать на этапе записи временных таблиц.

Что делать: протестируем на копии базы данных скорость расчета с отключенным флагом использования временных таблиц для СЛУ. Зачастую это позволяет сократить время расчета в несколько раз.

---

Шаг 3. Оптимизация при партионном учете

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

1. Оптимизация процедуры расчета списания по средней

Замер производительности часто показывает, что узким местом является выполнение процедуры РассчитатьСписаниеПоСредней() в общем модуле КорректировкаСтоимости. В типовом коде выполняются тяжелые обходы коллекций в цикле.

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


// Пример оптимизации обращения к свойствам внутри цикла
Для Каждого СтрокаДвижений Из ТаблицаДвижений Цикл
    // Вместо постоянного обращения к структуре:
    // Номенклатура = СтрокаДвижений.Номенклатура;
    // Сделаем локальное кэширование параметров перед циклом, если это возможно,
    // или оптимизируем выборку данных через построитель запроса.
КонецЦикла;

2. Разбивка сложных запросов распределения

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

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

---

Шаг 4. Настройка и обслуживание MS SQL Server 2014

Когда база данных достигает критического размера (в нашем случае 399 ГБ), стандартных регламентных заданий 1С становится недостаточно. Требуется тонкая настройка СУБД.

1. Борьба с эффектом Parameter Sniffing

В MS SQL Server 2014 используется новый оптимизатор запросов (Cardinality Estimator), который при первом запуске сложного запроса расчета себестоимости кэширует план, ориентируясь на переданные параметры. При повторных запусках с другими параметрами этот план оказывается крайне неэффективным, что приводит к зависанию расчета.

Что делать: переведем СУБД на использование старого, более стабильного оптимизатора запросов 1С. Для этого выполним в SQL Server Management Studio (SSMS) следующий T-SQL скрипт для включения флагов трассировки:


-- Включение флага трассировки 9481 (использование старой версии оптимизатора)
-- и флага 4199 (активация исправлений оптимизатора) на глобальном уровне
DBCC TRACEON (9481, -1);
DBCC TRACEON (4199, -1);
GO

Также рекомендуется очистить кэш планов запросов непосредственно перед запуском расчета себестоимости в 1С:


-- Очистка кэша планов запросов СУБД
DBCC FREEPROCCACHE;
GO

2. Оптимизация системной базы данных TempDB

В процессе расчета себестоимости 1С создает миллионы временных таблиц в базе данных TempDB. Если она расположена на медленных дисках или имеет всего один файл данных, возникает бутылочное горлышко дискового ввода-вывода (IOPS).

Что делать:

  1. Перенесем файлы базы данных TempDB на самый быстрый доступный накопитель (в идеале — выделенный NVMe SSD или RAM-диск).
  2. Разделим базу данных TempDB на несколько файлов данных равного размера. Количество файлов должно быть равно количеству логических ядер процессора вашего сервера (но не более 8 файлов).
  3. Включим флаги трассировки 1117 (одновременное авторасширение всех файлов в группе) и 1118 (выделение полных экстентов):

-- Включение флагов оптимизации TempDB
DBCC TRACEON (1117, -1);
DBCC TRACEON (1118, -1);
GO

3. Внеочередное обслуживание индексов и статистик

Стандартное обслуживание СУБД раз в неделю не подходит для баз объемом 400 ГБ, где ежедневно регистрируются сотни тысяч движений. Если статистика устареет посреди месяца, SQL Server выберет неверный индекс для расчета себестоимости.

Что делать: настроим регулярное регламентное задание в MS SQL Server Agent, которое будет запускаться непосредственно за 1 час до начала расчета себестоимости. Задание должно выполнять дефрагментацию/перестроение индексов по ключевым таблицам регистров затрат и партий, а также полное обновление статистик:


-- Обновление статистик для всей базы данных с полным сканированием
EXEC sp_updatestats;

Для точечного перестроения индексов по таблицам регистров сведений РАУЗ используем команду:


-- Перестроение индексов конкретной таблицы регистра затрат (пример)
ALTER INDEX ALL ON _InfoRg12345 REBUILD WITH (ONLINE = ON);

---

Шаг 5. Методические и платформенные приемы

Иногда ускорить расчет помогают организационные настройки самой платформы 1С:Предприятие.

1. Проведение документа вне транзакции

При стандартном проведении документа «Расчет себестоимости выпуска» платформа 1С пытается выполнить все операции в рамках одной гигантской транзакции. На больших базах это приводит к переполнению лога транзакций SQL (LDF-файла) и нехватке оперативной памяти на сервере приложений.

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

2. Дробление расчета себестоимости по организациям

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

Что делать: создадим отдельные документы «Расчет себестоимости выпуска» по каждой организации. Запуск документов производим строго последовательно. Это кратно уменьшит объем обрабатываемых временных таблиц в рамках одного сеанса расчета.

3. Проверка актуальности итогов регистра

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

Что делать: перейдем в меню «Операция — Управление итогами» и убедимся, что итоги рассчитаны по текущий месяц включительно. Ни в коем случае не сдвигайте границу расчета итогов далеко вперед в будущее — это ухудшает работу оптимизатора запросов.

---

Резюме совместной работы

Мы детально разобрали архитектурные и системные причины замедления закрытия месяца в 1С:УПП. Чтобы вернуть расчет себестоимости к исходным показателям в несколько часов, рекомендуем выполнять оптимизацию по следующему чек-листу:

  1. Запустим замер производительности в конфигураторе 1С на копии базы данных и определим точное место зависания алгоритма.
  2. Если используется РАУЗ — найдем и устраним отрицательные остатки в НЗП и настроим исключения встречного выпуска.
  3. Настроим СУБД MS SQL: перенесем базу TempDB на SSD/NVMe, разобьем ее на файлы по количеству ядер и включим флаги трассировки 9481, 4199, 1117, 1118.
  4. Запустим регламент полного обновления статистик перед стартом расчета себестоимости.
  5. Попробуем провести документ в монопольном режиме с использованием функции «Провести вне транзакции».
← На главную