Как ускорить массовое изменение реквизитов и проведение документов в 1С?

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

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

Анализ проблемного кода

В исходном примере основной «тормоз» — это получение объекта документа через ПолучитьОбъект() в цикле. Каждый вызов этой функции загружает документ в память, что крайне ресурсоемко. Также выполнение записи в каждой итерации цикла без предварительной проверки модифицированности заставляет систему выполнять лишние транзакции и пересчеты.

Шаг 1. Оптимизация запроса

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

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


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    ТЧ.Ссылка,
               |    ТЧ.Номенклатура
               |ИЗ
               |    Документ.ЗаказКлиента.Товары КАК ТЧ
               |ГДЕ
               |    ТЧ.Ссылка.Проведен = ИСТИНА
               |    И ТЧ.ВариантОбеспечения = &СтарыйВариант
               |    И ТЧ.Ссылка.ДатаОтгрузки > &Дата";
Запрос.УстановитьПараметр("СтарыйВариант", Перечисления.ВариантыОбеспечения.Отгрузить);
// ... установка остальных параметров
Результат = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Шаг 2. Эффективная работа с объектом

Вместо перебора строк табличной части через поиск НайтиСтроки(), который создает дополнительную нагрузку, давайте будем работать с уже полученным объектом точечно. И самое важное — проверяйте свойство Модифицированность перед записью.


Пока Результат.Следующий() Цикл
    ДокументОбъект = Результат.Ссылка.ПолучитьОбъект();
    Изменен = Ложь;
    Для Каждого СтрокаТЧ Из ДокументОбъект.Товары Цикл
        Если СтрокаТЧ.ВариантОбеспечения = Перечисления.ВариантыОбеспечения.Отгрузить Тогда
            СтрокаТЧ.ВариантОбеспечения = Перечисления.ВариантыОбеспечения.НеТребуется;
            Изменен = Истина;
        КонецЕсли;
    КонецЦикла;

    Если Изменен Тогда
        ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
    КонецЕсли;
КонецЦикла;

Шаг 3. Использование транзакций

Запись каждого документа — это отдельная транзакция в базе данных. Если документов тысячи, это создает огромные очереди блокировок. Ускорить процесс поможет группировка записей в транзакции. Например, записывать по 50 документов за раз.


Счетчик = 0;
НачатьТранзакцию();
// ... в цикле обработки ...
Счетчик = Счетчик + 1;
Если Счетчик % 50 = 0 Тогда
    ЗафиксироватьТранзакцию();
    НачатьТранзакцию();
КонецЕсли;
// ... после цикла ...
ЗафиксироватьТранзакцию();

Рекомендации по отладке

  1. Замер производительности: Используйте инструмент «Замер производительности» в Конфигураторе. Он покажет, что именно занимает больше времени: запрос или процесс записи документа (события модуля объекта).
  2. Групповое изменение реквизитов: Всегда задавайтесь вопросом: можно ли решить задачу типовым инструментом? «Групповое изменение реквизитов» — отличный способ избежать написания самописного кода, если задача разовая.
  3. Фоновое выполнение: Если процедура работает долго, выносите ее в РегламентныеЗадания или используйте ЗапуститьФоновоеЗадание. Это позволит пользователям не ждать окончания процесса в интерфейсе.

Таким образом, комбинируя правильную фильтрацию в запросе, использование транзакций и проверку на модифицированность, вы сможете существенно ускорить выполнение любой массовой обработки данных в 1С.

← На главную