Как правильно оптимизировать запрос в цикле при проверке остатков и что отвечать на этот вопрос на собеседовании

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

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

Почему запрос в цикле — это «яд» для производительности системы

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

  1. Сетевые задержки (Latency): Каждый вызов функции с запросом — это отдельное обращение сервера приложений к серверу СУБД. Если в документе 100 строк, система выполнит 100 сетевых запросов. Накладные расходы на установку соединения и передачу данных часто превышают время выполнения самого запроса.
  2. Нагрузка на СУБД: SQL-сервер вынужден 100 раз компилировать план запроса, выделять ресурсы и выполнять поиск по индексам. Один массивный запрос обрабатывается оптимизатором гораздо эффективнее.
  3. Блокировки: При многопользовательской работе постепенное накладывание блокировок в цикле (строка за строкой) значительно повышает риск возникновения Deadlocks (взаимных блокировок).

Техническое решение: Переход от единичных проверок к пакетной обработке

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

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

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


// Подготавливаем таблицу товаров из документа
ТаблицаТоваров = Объект.Товары.Выгрузить( , "Номенклатура, Серия");
ТаблицаТоваров.Свернуть("Номенклатура, Серия");

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

Запрос.УстановитьПараметр("ТаблицаТоваров", ТаблицаТоваров);
Запрос.УстановитьПараметр("Период", ДатаПроверки);

// Загружаем результат в Соответствие для быстрого поиска в памяти
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
КэшОстатков = Новый Соответствие;

Для Каждого Стр Из РезультатЗапроса Цикл
    // Ключом будет структура или строка для уникальной идентификации
    Ключ = Строка(Стр.Номенклатура.УникальныйИдентификатор()) + "_" + Строка(Стр.Серия.УникальныйИдентификатор());
    КлючОстатков.Вставить(Ключ, Стр.Остаток);
КонецЦикла;

Шаг 3. Быстрая проверка в цикле по кэшу. Теперь, когда данные получены одним запросом, мы можем итерировать строки документа и проверять наличие остатка в объекте Соответствие. Это выполняется в оперативной памяти мгновенно.

Разбор вариантов ответов на собеседовании

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

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

Как поступить профессионалу: алгоритм действий

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

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

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

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

← На главную