Центр Диагностики & База Системных Ошибок

Решения для Windows Server, Active Directory, 1С, СУБД, Linux, Cisco, MikroTik и IP-телефонии.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, баз данных и сетевого оборудования. Перед выполнением действий обязательно создайте резервную копию. При отсутствии необходимой квалификации обратитесь к ИТ-специалистам.
PERF_BATCH_TABULAR_PROCESSING 1С:Предприятие и СУБД

Гайд 1С: Оптимизация работы с табличными частями при пакетной обработке

Обновлено: 26.08.2026  ·  Официальная база знаний
  • Обработка документов с десятками тысяч строк длится часами при 100% загрузке одного ядра процессора.
  • Множественные циклические запросы к СУБД внутри конструкции Для Каждого СтрокаТЧ Из... (ошибка «Запрос в цикле»).
  • Неконтролируемый рост времени выполнения транзакций и удержание блокировок.

1. Исключение запросов внутри цикла (Векторизация)

// НЕПРАВИЛЬНО: Запрос в цикле по строкам табличной части
Для Каждого Стр Из ДокументОбъект.Товары Цикл
    Запрос = Новый Запрос("ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныГдеНоменклатура = &Ном");
    Запрос.УстановитьПараметр("Ном", Стр.Номенклатура);
    Стр.Цена = Запрос.Выполнить().Выгрузить()[0].Цена;
КонецЦикла;

// ПРАВИЛЬНО: Пакетная передача всей ТЧ во временную таблицу
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ТЧ.НомерСтроки КАК НомерСтроки,
    |   ТЧ.Номенклатура КАК Номенклатура
    |ПОМЕСТИТЬ ВТ_Товары
    |ИЗ
    |   &ТабличнаяЧасть КАК ТЧ;
    |////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   ВТ.НомерСтроки,
    |   ЕСТЬNULL(Цены.Цена, 0) КАК Цена
    |ИЗ
    |   ВТ_Товары КАК ВТ
    |   ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(&Период, ) КАК Цены
    |       ПО ВТ.Номенклатура = Цены.Номенклатура";

Запрос.УстановитьПараметр("ТабличнаяЧасть", ДокументОбъект.Товары.Выгрузить());
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Результат = Запрос.Выполнить();
ДокументОбъект.Товары.ЗагрузитьКолонку(Результат.Выгрузить().ВыгрузитьКолонку("Цена"), "Цена");

2. Пакетная фиксация транзакций порциями

При обработке сотен тысяч строк разделяйте работу на кванты транзакций с явной фиксацией:

Счетчик = 0;
НачатьТранзакцию();
Для Каждого Строка Из МассивОбъектов Цикл
    ОбработатьСтроку(Строка);
    Счетчик = Счетчик + 1;
    Если Счетчик % 1000 = 0 Тогда
        ЗафиксироватьТранзакцию();
        НачатьТранзакцию();
    КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
Практический опыт инженера: При передаче ТаблицыЗначений в запрос типизируйте все колонки перед выгрузкой — бестиповые колонки заставляют СУБД создавать поля nvarchar(max), что исключает эффективное использование индексов во временных таблицах.

Частые вопросы (FAQ)

Почему запрос в цикле так сильно замедляет работу?

Каждый вызов запроса в цикле создает отдельный сетевой раундтрип между rphost и СУБД, компиляцию плана и наложение блокировок. Обработка 10 000 строк порождает 10 000 отдельных транзакций вместо одной пакетной.

Какой размер пачки (батча) транзакции считается оптимальным?

Оптимальный размер батча для 1С составляет от 500 до 2 000 объектов/строк. Меньший размер увеличивает накладные расходы на коммиты, больший — приводит к блокировкам и раздуванию журналов СУБД.

Как метод ЗагрузитьКолонку() сопоставляет строки?

Метод платформы 1С ЗагрузитьКолонку() выполняет прямое позиционное сопоставление по индексам элементов массива, работая на уровне низкоуровневой памяти C++ со скоростью в сотни раз выше перебора в цикле.

Создает ли передача ТЧ в запрос дополнительную нагрузку на tempdb?

Да, платформа создает физическую временную таблицу (#tt) в tempdb СУБД, но благодаря оптимизации Bulk Insert это происходит на порядки быстрее одиночных чтений.