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

- Исходный учебный фрагмент с понятной проблемой
- Комментарии проверяющего по скорости и правильности работы
- Вариант исправления без запроса на каждом проходе цикла
- Список повторной проверки после изменения кода
Содержание
Условие учебного примера
Задача простая: рассчитать сумму строк табличной части по последним зарегистрированным ценам. Названия объектов здесь условные. В реальной конфигурации нужно взять объекты проекта и отдельно проверить правила получения цены.
В исходном варианте разработчик получает цену отдельным запросом для каждой строки. На маленьком наборе данных результат выглядит корректно, поэтому проблема часто остаётся незаметной до роста документа или нагрузки.
Для Каждого СтрокаТовара Из Товары Цикл
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &ДатаСреза, Номенклатура = &Номенклатура
| ) КАК Цены";
Запрос.УстановитьПараметр("ДатаСреза", ДатаСреза);
Запрос.УстановитьПараметр("Номенклатура", СтрокаТовара.Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СтрокаТовара.Сумма = СтрокаТовара.Количество * Выборка.Цена;
КонецЕсли;
КонецЦикла;Что я отмечу при проверке
Количество запросов растёт вместе с количеством строк. Документ из ста строк даст до ста похожих обращений к регистру. На маленьком примере всё может выглядеть нормально, а на рабочих объёмах появятся задержки и лишняя нагрузка.
Есть и вторая проблема: мы не решили, что делать, если цена не найдена. Оставить ноль, показать предупреждение или остановить расчёт? Это нужно согласовать до изменения кода, иначе ускорение незаметно поменяет поведение системы.
- Зафиксировать число строк и число обращений к данным до изменения.
- Уточнить момент среза и правила выбора вида цены.
- Определить поведение для пустой номенклатуры и отсутствующей цены.
- Не переносить расчёт на клиент только ради визуального ускорения.
Как можно исправить
Я бы сначала собрал уникальную номенклатуру, одним запросом получил цены и сложил их в соответствие. После этого строки можно рассчитать без новых обращений к базе. Это учебная схема: в рабочем проекте придётся учесть вид цен, характеристики, соглашения, валюту и правила конкретной конфигурации.
НоменклатураДляЗапроса = Новый Массив;
Для Каждого СтрокаТовара Из Товары Цикл
Если ЗначениеЗаполнено(СтрокаТовара.Номенклатура)
И НоменклатураДляЗапроса.Найти(СтрокаТовара.Номенклатура) = Неопределено Тогда
НоменклатураДляЗапроса.Добавить(СтрокаТовара.Номенклатура);
КонецЕсли;
КонецЦикла;
ЦеныПоНоменклатуре = Новый Соответствие;
Если НоменклатураДляЗапроса.Количество() > 0 Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура КАК Номенклатура,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &ДатаСреза, Номенклатура В (&Номенклатура)
| ) КАК Цены";
Запрос.УстановитьПараметр("ДатаСреза", ДатаСреза);
Запрос.УстановитьПараметр("Номенклатура", НоменклатураДляЗапроса);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЦеныПоНоменклатуре.Вставить(Выборка.Номенклатура, Выборка.Цена);
КонецЦикла;
КонецЕсли;
Для Каждого СтрокаТовара Из Товары Цикл
Цена = ЦеныПоНоменклатуре.Получить(СтрокаТовара.Номенклатура);
Если Цена = Неопределено Тогда
ВызватьИсключение "Для позиции не найдена цена";
КонецЕсли;
СтрокаТовара.Сумма = СтрокаТовара.Количество * Цена;
КонецЦикла;Как проверить исправление
Разбор не заканчивается на более красивом коде. Повторите основной сценарий на тех же данных, пройдите крайние случаи и сравните количество обращений к базе. Если поведение изменилось, это должно быть частью задачи, а не случайным последствием ускорения.
- Пустая табличная часть не вызывает ошибку и не делает лишний запрос.
- Повторяющаяся номенклатура попадает в набор запроса один раз.
- Отсутствующая цена обрабатывается согласованным способом.
- Сумма совпадает с исходным вариантом на корректных данных.
- Количество запросов не зависит от количества строк документа.
Как выглядит полезный разбор кода
Полезное замечание отвечает на четыре вопроса: что я увидел, чем это опасно, как повторить проблему и по какому признаку принять исправление. Фраза «перепиши запрос» ничему не учит. А формулировка «сейчас выполняется один запрос на строку; получи данные одним обращением и покажи проверку отсутствующей цены» оставляет понятную задачу для самостоятельной работы.
В менторстве после такого разбора ученик делает следующую попытку сам. Этот пример показывает мой подход, но правила конкретной конфигурации и измерения на рабочей базе всё равно нужно проверять отдельно.
Самопроверка
Частые вопросы
Почему нельзя просто оставить запрос в цикле?
На малом наборе это может быть незаметно, но число обращений к базе растёт вместе с количеством строк. Один наборный запрос обычно предсказуемее и легче измеряется.
Можно ли копировать исправленный код в рабочую конфигурацию?
Нет без проверки. Имена объектов условные, а правила цен зависят от конфигурации. Используйте пример как схему разбора и обязательно проверяйте метаданные и требования проекта.
Что важнее при разборе: стиль или скорость работы?
Сначала правильность и риски для данных, затем скорость и удобство дальнейшей поддержки. Стиль важен, но он не должен скрывать более серьёзную ошибку в поведении.
Первичные источники
Что проверить дополнительно
Полезный материал
Поделиться статьёй
Сохраните материал или отправьте его тому, кому он пригодится.
Следующий шаг
Хотите получать разбор собственных решений?
Посмотрите, как в менторстве устроены практика, повторная попытка и ручная проверка.