Избавиться от запроса в цикле

1. 24.11.21 11:54 Сейчас в теме
Приветствую, Форумчане!
УФ, учебная задача

В процедуре проведения в регистре накопления документа использую следующий код:

Пока Выборка.Следующий Цикл
..................
КритерийОтказа = ПроверкаНаНаличие(Выборка.Номенклатура, Количество);
Отказ = КритерийОтказа.ОтказДа;
..................


Сама функция ПроверкаНаНаличие(Выборка.Номенклатура, Количество) большая с большим запросом

В этой функции есть операции добавления в ТЗ

ТК = ТаблицаКомплектующих.Добавить();
.......
ТК.Номенклатура = ВыборкаЗапрос.Номенклатура;
ТК.Комплект          = ВыборкаЗапрос.Номенклатура.ЭтоКомплект;
....................


Джедай написал, что это плохо использовать запрос в цикле, в частности претензии по
ВыборкаЗапрос.Номенклатура.ЭтоКомплект;


Неужели в запросе "ВыборкаЗапрос" реквизит "ЭтоКомплект" выводит в отдельную колонку? разъясните смысл ошибки и как с этим справится?
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. nomad_irk 58 24.11.21 12:00 Сейчас в теме
(1)Да, необходимо выводить в отдельную колонку.
Суть ошибки в том, что разыменование(обращение через точку) вызывает не явный запрос к БД.
Справится - получать запросом сразу необходимые данные, чтобы не выполнять разыменовывание.
7. Sashares 19 24.11.21 12:32 Сейчас в теме
(1)
Джедай написал, что это плохо использовать запрос в цикле, в частности претензии по
ВыборкаЗапрос.Номенклатура.ЭтоКомплект;


У вас и так запрос, так нахера вы после запроса вытаскиваете реквизит номенклатуры через точку, если можно в запросе сразу его получить?
При получении реквизита через точку в память считывается весь объект. В данном случае это бессмысленный расход ресурсов.
3. laperuz 47 24.11.21 12:08 Сейчас в теме
И плюс у вас в
Пока Выборка.Следующий Цикл
вызывается
ПроверкаНаНаличие
, в которой тоже запрос, это тоже запрос в цикле.
5. ukraina 24.11.21 12:26 Сейчас в теме
(3) Да, это был следующий вопрос про цикл в запросе. Но как с этим тогда справиться?
Там идет проверка и большой запрос
11. nomad_irk 58 24.11.21 12:43 Сейчас в теме
(5)Дополнить запрос проверки запросом к ТЧ документа.
4. starjevschik 24.11.21 12:25 Сейчас в теме
Есть один большой секрет. Только чур никому!
Так вот. Если вопросов к производительности нет и работает все правильно, можно оставить как есть. Совершенно неважно, как там запрос или его вообще нет, никто никогда этого не увидит.
Только тс-с-с-с!
6. ukraina 24.11.21 12:27 Сейчас в теме
(4)Работает то правильно, но вот заметили :-)
9. Dem0 8 24.11.21 12:40 Сейчас в теме
(4)
Если вопросов к производительности нет и работает все правильно, можно оставить как есть. Совершенно неважно, как там запрос или его вообще нет, никто никогда этого не увидит.

Не чини не сломанное? =)
8. ukraina 24.11.21 12:37 Сейчас в теме
Есть еще один кусок кода проведения документа поступления товара. Сделал классикой по учебнику с помощью помощника...

Для Каждого СТР Из Товары Цикл
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.Номенклатура = СТР.Номенклатура;
Движение.Комплект = СТР.Номенклатура.ЭтоКомплект;


Это тоже Запрос в цикле? И как здесь тогда бороться? Выводить новый реквизит в ТЧ "Товары" - "ЭтоКомплект"?

Или Делать запрос к табличной части "Товары", там получать "ЭтоКомплект" и потом делать обход по запросу?
10. nomad_irk 58 24.11.21 12:43 Сейчас в теме
(8)Да. это запрос в цикле.
Делать - второй вариант.
17. herfis 428 25.11.21 16:38 Сейчас в теме
(8)
Или Делать запрос к табличной части "Товары", там получать "ЭтоКомплект" и потом делать обход по запросу?

Да, в типовых так и делается.
Запрос в цикле, да если еще цикл на большое количество итераций да в обработке проведения - считается очень большим злом.
Суть в том, что работа с базой данных - обычно самое узкое место в 1С и по производительности и по масштабируемости (возможностям параллельной работы в том числе). Даже простые запросы имеют ощутимые накладные расходы. А цикл умножает эту беду на количество итераций, что особенно печально в части масштабируемости. Ибо общая производительность будет падать пропорционально количеству итераций. Другими словами кроме текущей плохой эффективности это может сработать еще и как мина замедленного действия, если характер работы с конфигурацией приведет к увеличению количества итераций.
В запущенных случаях избавление от запросов в цикле дает прирост производительности даже не в разы, а в десятки и сотни раз.
А обращение через точку даже в единичных случаях бывает не очень хорошо. Потому что само по себе оно выполняется не очень оптимально - при этом вычитывается весь объект (вместе с табличными частями), а не только требуемый реквизит (зато на некоторое время этот объект кэшируется и повторное обращение к нему уже не вызовет запроса к базе данных). Чем "тяжелее" объект, тем менее эффективно будет обращаться к нему через точку за значением его реквизита. Поэтому в типовых есть специальные функции, которые вместо обращения через точку получают нужный реквизит явным запросом.
ЗЫ. А вы думали - вводный учебник прошли и можно промышленные базы программировать? :)
12. Pixar0000 24.11.21 13:21 Сейчас в теме
(8)
СТР.Номенклатура

вы все равно получаете весь объект, так что не критично разименовывание
13. Sashares 19 24.11.21 13:25 Сейчас в теме
(12)Стр.Номенклатура это колонка табличной части документа.
К получению объекта Номенклатуры при разыменовании это отношения не имеет.

Если у номенклатуры нет табличных частей, и в документе не много строк, то да, это не критично.
14. ukraina 24.11.21 17:13 Сейчас в теме
Для Каждого СТР Из Товары Цикл
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.Номенклатура = СТР.Номенклатура;
Движение.Комплект = СТР.Номенклатура.ЭтоКомплект;


Ну неужели из-за одного реквизита создавать запрос для обхода?

А такой вариант будет нормальным?

Движение.Комплект = ПолучитьЗначениереквизита(СТР.Номенклатура);

&НаСервере
Функция ПолучитьЗначениереквизита(Номенклатура)
Возврат Номенклатура.ЭтоКомплект;
КонецФункции
15. Sashares 19 24.11.21 19:00 Сейчас в теме
(14) А что по вашему изменилось в этом варианте?
16. laperuz 47 24.11.21 20:29 Сейчас в теме
(14)Представьте, что вам нужно войти в комнату, где сидит 10 человек и узнать возраст каждого. Ваш вариант-зайти в комнату-спросить возраст первого-выйти из комнаты. И так 10 раз. А запрос - зайти 1 раз и у всех сразу спросить возраст. Может быть в первом варианте вы и не сильно устанете, но что, если комнат 1000 и в каждой по тысяче человек?)
Оставьте свое сообщение
Вопросы с вознаграждением
Вакансии
Программист, аналитик, эксперт 1С
Санкт-Петербург
По совместительству

Программист 1С
Севастополь
зарплата от 150 000 руб. до 200 000 руб.
Полный день

Программист 1С
Москва
зарплата от 120 000 руб.
Полный день

Ведущий программист-консультант 1С (УХ)
Москва
зарплата от 250 000 руб. до 250 000 руб.
Полный день

Программист 1С (розница)
Москва
зарплата от 160 000 руб. до 160 000 руб.
Полный день