Как оптимизировать проведение по партиям и ускорить работу обработчика "ДвижениеПартийТоваров" в 1С:Управление торговлей 10.3?

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

При работе в конфигурациях на обычных формах, таких как «1С:Управление торговлей 10.3» или «1С:Управление производственным предприятием 1.3», многие разработчики и системные администраторы сталкиваются со значительным замедлением системы при проведении документов. Особенно остро эта проблема проявляется в документах массового спроса — например, таких как Отчет о розничных продажах или Реализация товаров и услуг.

Основным «пожирателем» времени при проведении этих документов выступает общий модуль УправлениеЗапасамиПартионныйУчет и его экспортируемая процедура ДвижениеПартийТоваров. Время проведения одного документа может возрастать до 15–20 секунд, а при попытке группового перепроведения за длительный период система практически полностью парализуется. В этой статье мы подробно разберем причины этой проблемы и рассмотрим три эффективных способа ее решения.

Выясняем причину: почему «тормозит» партионный учет?

Если мы запустим замер производительности в конфигураторе 1С во время проведения «тяжелого» документа, то увидим, что более 90% времени выполнения транзакции уходит на получение остатков партий. Проанализируем, где именно происходят задержки. Внутри общего модуля УправлениеЗапасамиПартионныйУчет находятся ключевые функции получения остатков:

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


Номенклатура В (
    ВЫБРАТЬ Номенклатура 
    ИЗ РегистрСведений.СписанныеТовары 
    ГДЕ Регистратор = &Ссылка
)

Почему это работает медленно на SQL Server и PostgreSQL? При таком синтаксисе СУБД часто не может построить оптимальный план запроса. Вместо быстрого поиска по индексу (Index Seek) оптимизатор СУБД выбирает сканирование всей таблицы остатков партий (Table Scan / Index Scan) либо использует неоптимальные соединения типа Nested Loops. Когда база данных содержит миллионы записей за несколько лет работы, этот запрос начинает выполняться критически долго. Это также приводит к массовым взаимоблокировкам (deadlocks) и ошибкам транзакций у пользователей.

---

Решение 1. Оптимизация запроса через индексированные временные таблицы

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

Разберем этот процесс по шагам:

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

Посмотрим на пример того, как должен выглядеть оптимизированный пакет запросов:


// Шаг 1. Помещаем списанные товары во временную таблицу
ВЫБРАТЬ
    СписанныеТовары.Номенклатура КАК Номенклатура,
    СписанныеТовары.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    СписанныеТовары.Склад КАК Склад
ПОМЕСТИТЬ ВТ_СписанныеТовары
ИЗ
    РегистрСведений.СписанныеТовары КАК СписанныеТовары
ГДЕ
    СписанныеТовары.Регистратор = &Ссылка

ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    ХарактеристикаНоменклатуры,
    Склад
;

// Шаг 2. Основной запрос получения остатков партий
ВЫБРАТЬ
    ПартииОстатки.Номенклатура КАК Номенклатура,
    ПартииОстатки.ДокументОприходования КАК ДокументОприходования,
    ПартииОстатки.КоличествоОстаток КАК КоличествоОстаток,
    ПартииОстатки.СтоимостьОстаток КАК СтоимостьОстаток
ИЗ
    РегистрНакопления.ПартииТоваровНаСкладах.Остатки(
        &МоментВремени,
        Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ВТ_СписанныеТовары)
    ) КАК ПартииОстатки

Благодаря явному использованию индексированной временной таблицы ВТ_СписанныеТовары, СУБД мгновенно определяет точный список номенклатуры и строит идеальный план запроса. На практике этот шаг сокращает время проведения одного документа с 15–20 секунд до десятых долей секунды.

---

Решение 2. Переход на регламентное (отложенное) проведение по партиям

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

Проанализируем этот механизм подробнее. По умолчанию в 1С:УТ 10.3 настроено списание партий в режиме реального времени («онлайн»). Это значит, что при проведении каждого документа система пытается сразу рассчитать себестоимость списания. Если снять эту нагрузку с пользователей, документы будут проводиться мгновенно (за 1–2 секунды), так как они не будут обращаться к регистру партий.

Разберем, как настроить отложенное проведение по шагам:

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

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

---

Решение 3. Регламентное обслуживание СУБД и обновление статистики

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

Когда статистика СУБД по этим таблицам «устаревает», оптимизатор SQL-сервера начинает строить неверные планы выполнения даже для оптимизированных запросов. Для решения этой проблемы необходимо настроить регулярное обслуживание базы данных:

Резюме

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

← На главную