Правило
Заголовок раздела «Правило»Однотипные данные получайте одним запросом, а не серией запросов в цикле. Список
значений для отбора передавайте параметром (В (&Список)), для сложных наборов —
через временную таблицу. Это касается и неявных запросов: ПолучитьОбъект(),
разыменование ссылки через точку и НайтиПоНаименованию() внутри цикла — те же
запросы к СУБД.
Запрос в цикле превращает одну операцию с СУБД в N операций: N раз компиляция плана, N сетевых обращений, N блокировок. На двух тестовых элементах это незаметно, на боевой тысяче — секунды и минуты. Это самая частая причина «медленной обработки» на проде при зелёных тестах.
Тот же приём в языке запросов:
ВЫБРАТЬ БанковскиеСчета.Ссылка КАК СчетИЗ Справочник.БанковскиеСчета КАК БанковскиеСчетаГДЕ БанковскиеСчета.Банк В (&БанкиДляОбработки)Составной ключ — через временную таблицу
Заголовок раздела «Составной ключ — через временную таблицу»Когда отбор идёт не по одному полю, а по комбинации (номенклатура + склад,
номер + дата), В (&Список) не подходит. Таблица значений с ключами передаётся
параметром и соединяется с данными:
Запрос.УстановитьПараметр("ТаблицаКлючей", ТаблицаКлючей); // ТЗ: Номенклатура, СкладЗапрос.Текст ="ВЫБРАТЬ Ключи.Номенклатура, Ключи.Склад|ПОМЕСТИТЬ КлючиОтбора|ИЗ &ТаблицаКлючей КАК Ключи|;|ВЫБРАТЬ Остатки.Номенклатура, Остатки.Склад, Остатки.КоличествоОстаток|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки| ВНУТРЕННЕЕ СОЕДИНЕНИЕ КлючиОтбора КАК Ключи| ПО Остатки.Номенклатура = Ключи.Номенклатура И Остатки.Склад = Ключи.Склад";Неявные запросы в цикле
Заголовок раздела «Неявные запросы в цикле»Запрос в цикле не всегда выглядит как Новый Запрос. Каждая из этих конструкций
внутри цикла — то же обращение к СУБД на каждой итерации:
Ссылка.Реквизит(разыменование через точку) — запрос за объектом;ПолучитьОбъект(),НайтиПоНаименованию(),НайтиПоКоду();- обращение к виртуальной таблице (остатки, срез последних) с отбором по текущему элементу цикла.
Явные случаи подсвечивает диагностика CreateQueryInCycle; неявные она не
видит — их выдаёт замер производительности: один и тот же текст запроса с
счётчиком в тысячи выполнений.
Пример из практики
Заголовок раздела «Пример из практики»В загрузке продаж из ДодоИс сопоставление
номенклатуры и проверка ставки НДС выполняются для каждой строки выгрузки. Поиск
«в лоб» — НайтиПоНаименованию и разыменование ставки в цикле — это два скрытых
запроса на строку, тысячи запросов на дневную выгрузку. Правильно: до цикла один
запрос собирает соответствие «внешний ключ → номенклатура, ставка НДС» в
Соответствие, и цикл работает уже с ним — в коде стадии валидации это строка
СтавкиНДСНоменклатуры[СтрокаДодоИс.Номенклатура].

Когда не применять
Заголовок раздела «Когда не применять»- Следующий запрос действительно зависит от результата предыдущего и не сводится к пакетному запросу или временной таблице (редкий случай — обычно сводится).
- Порционная обработка больших объёмов (чанкование по 1000 записей): серия запросов осознанна, но каждый запрос обрабатывает пачку, а не один элемент.
- Разовые административные скрипты на малом объёме, где читаемость важнее миллисекунд, — допустимо, но не в коде, попадающем в конфигурацию.
См. также
Заголовок раздела «См. также»- Идемпотентность обработчиков обмена — там тот же приём применяется к поиску по идентификатору сообщения.