Задавался вопросом как оптимальнее вывести данные в списке.
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
СписокЗадач = Новый СписокЗначений;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
СписокЗадач.Добавить(ОформлениеСтроки.ДанныеСтроки.Ссылка);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних КАК ВремяРаботыТехподдержкиСрезПоследних
|ГДЕ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо В(&СписокЗадач)";
Запрос.УстановитьПараметр("СписокЗадач", СписокЗадач);
ТаблицаЗадач = Запрос.Выполнить().Выгрузить();
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
НайденнаяСтрока = ТаблицаЗадач.Найти(ОформлениеСтроки.ДанныеСтроки.Ссылка,"ЗадачаИнженера");
Если НайденнаяСтрока = Неопределено Тогда
ОформлениеСтроки.Ячейки.Выполнено.Значение = 0;
Иначе
ОформлениеСтроки.Ячейки.Выполнено.Значение = НайденнаяСтрока.ВыполненоНаСегодня;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Показать
Результат производительности хуже чем
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних КАК ВремяРаботыТехподдержкиСрезПоследних
|ГДЕ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо = &РаботаПо";
Запрос.УстановитьПараметр("РаботаПо", ОформлениеСтроки.ДанныеСтроки.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Выполнено = Выборка.ВыполненоНаСегодня;
КонецЦикла;
ОформлениеСтроки.Ячейки.Выполнено.Значение = Выполнено;
КонецЦикла;
КонецПроцедуры
Показать
Первый код: 0,857456
Второй код: 0,350234
Хоть я и получаю ТЗ, но запрос выполняете дольше(3 раза вызывался), чем получение одного реквизита тип строка в запросом в цикле(43 раза вызывался)?
(6) Xershi, это не дало результата замер: 0,438890
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
СписокЗадач = Новый СписокЗначений;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
СписокЗадач.Добавить(ОформлениеСтроки.ДанныеСтроки.Ссылка);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних КАК ВремяРаботыТехподдержкиСрезПоследних
|ГДЕ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо В(&СписокЗадач)";
Запрос.УстановитьПараметр("СписокЗадач", СписокЗадач);
ТаблицаЗадач = Новый ТаблицаЗначений;
ТаблицаЗадач.Колонки.Добавить("ЗадачаИнженера");
ТаблицаЗадач.Колонки.Добавить("ВыполненоНаСегодня");
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТаблицаЗадач.Добавить();
НоваяСтрока.ЗадачаИнженера = Выборка.ЗадачаИнженера;
НоваяСтрока.ВыполненоНаСегодня = Выборка.ВыполненоНаСегодня;
КонецЦикла;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
НайденнаяСтрока = ТаблицаЗадач.Найти(ОформлениеСтроки.ДанныеСтроки.Ссылка,"ЗадачаИнженера");
Если НайденнаяСтрока = Неопределено Тогда
ОформлениеСтроки.Ячейки.Выполнено.Значение = 0;
Иначе
ОформлениеСтроки.Ячейки.Выполнено.Значение = НайденнаяСтрока.ВыполненоНаСегодня;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
(6) может быть.. возможно время на создание таблицы тут имеет значение, попробуйте так же с выборкой.
Или для начала можно разделить выполнение запроса и получение данных из него. Так можно будет посмотреть, где же бОльшее время тратится:
Результат = Запрос.Выполнить();
ТаблицаЗадач = Результат .Выгрузить();
Просто в моей публикации http://infostart.ru/public/406155/ Оставили комментарий, что лучше сделать один запрос. Но выходит что этот запрос получится не оптимальный! И результат будет хуже...
Стою в начале списка, включаю замер.
Жму контр+енд оказываюсь в конце списка!
Выключаю замер 3 раза запрос выполняется.
В коде формы документа списка только эта процедура!
Код Модуля и менеджера пустой.
По поводу 3 вызовов из (12).
Первый вызов это все видимые строки на таблице.
Второй вызов это первые 4 видимых строки на таблице.
Третий вызов это первая строка выше видимых строк на таблице.
(13) он имеет ввиду, получать только для "новых" строк.
т.е. выполняем запрос, в переменную запоминаем список обработанных ссылок, в следующем запросе (опять произошло обновление табличного поля) получаем данные, исключая ссылки, обработанные при прошлом срабатывании события. Заменяем список обработанных ссылок на текущий и так далее.
Ну это я так понял )
(20) скорее всего вариант с виртуальными параметрами все решит.
я имел ввиду следующее:
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В (&СписокЗадач) И НЕ РаботаПо В (&СписокЗадачПрошлыйЗапрос)) КАК ВремяРаботыТехподдержкиСрезПоследних"
главное, чтобы так строки не очистились, которые в прошлый раз заполняли, а в этот "соптимизировали" и пропустили.. уже давновато с обычными формами не работал
(24) sommid, Боже мой! Что это? Даже если бы это работало, то в этом нет никакого смысла. Размер порции данных для таких запросов всегда заведомо ограничен и дополнительное уменьшение размера выборки никакого практического эффекта не даст.
(25) скорее всего ). смутила большая разница в замерах, но это должно быть из-за ГДЕ, а не отбора через виртуальные параметры.
Ну и для проведения опыта почему нет, тут же доли секунд экономим? сделал, посмотрел на результат - если толку нет, то пропустил и забыл
(25) + это при многократном вызове платформы позволит вообще не выполнять запрос и обход, если списки текущий и предыдущий совпадут, а это уже ~2/3 от затраченного времени (в начале автор писал, что вызывается трижды)
(28) sommid, Если речь о кэшировании запрашиваемых данных - то это другой разговор. Но с кэшем куча своих проблем возникает. Контроль размера, контроль времени жизни. А чтобы подряд ПолучениеДанных() на одни и те же оформления строк получало - такого я не замечал. Несколько вызовов на разные порции - да. Чаще всего наблюдал два вызова подряд.
ВЫБРАТЬ
ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
ИЗ
РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В(&СписокЗадач)) КАК ВремяРаботыТехподдержкиСрезПоследних
Проверил результат не дает переписка запроса.
Когда таблица вручную создается: 0,456324
Когда выгружается: 0,430917
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
СписокЗадач = Новый СписокЗначений;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
СписокЗадач.Добавить(ОформлениеСтроки.ДанныеСтроки.Ссылка);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В (&СписокЗадач)) КАК ВремяРаботыТехподдержкиСрезПоследних";
Запрос.УстановитьПараметр("СписокЗадач", СписокЗадач);
ТаблицаЗадач = Запрос.Выполнить().Выгрузить();
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
НайденнаяСтрока = ТаблицаЗадач.Найти(ОформлениеСтроки.ДанныеСтроки.Ссылка,"ЗадачаИнженера");
Если НайденнаяСтрока = Неопределено Тогда
ОформлениеСтроки.Ячейки.Выполнено.Значение = 0;
Иначе
ОформлениеСтроки.Ячейки.Выполнено.Значение = НайденнаяСтрока.ВыполненоНаСегодня;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Соответствие = Новый Соответствие;
МассивСсылок = Новый Массив;
Для Каждого Строка Из ОформленияСтрок Цикл
МассивСсылок.Добавить(Строка.ДанныеСтроки.Ссылка);
Соответствие.Вставить(Строка.ДанныеСтроки.Ссылка, Строка);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В (&СписокЗадач)) КАК ВремяРаботыТехподдержкиСрезПоследних";
Запрос.УстановитьПараметр("СписокЗадач", МассивСсылок);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Соответствие.Получить(ВыборкаДетальныеЗаписи.ЗадачаИнженера).Ячейки.Выполнено.УстановитьТекст("" + ВыборкаДетальныеЗаписи.ВыполненоНаСегодня);
КонецЦикла;
ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, ) КАК ВремяРаботыТехподдержкиСрезПоследних
данные выбираются только один раз. Потом уже из кеша считываются (данные в таблице не менялись во время цикла). При "виртуальном" параметре они каждый раз выбираются. Да и это заметно на встроенной базе 1С. С SQL будет немного не так. Но тоже быстрее, срезПоследних целиком в памяти еще будет, но добавятся накладные расходы.
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Соответствие = Новый Соответствие;
МассивСсылок = Новый Массив;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
МассивСсылок.Добавить(ОформлениеСтроки.ДанныеСтроки.Ссылка);
Соответствие.Вставить(ОформлениеСтроки.ДанныеСтроки.Ссылка, ОформлениеСтроки);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В (&СписокЗадач)) КАК ВремяРаботыТехподдержкиСрезПоследних";
Запрос.УстановитьПараметр("СписокЗадач", МассивСсылок);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Соответствие.Получить(Выборка.ЗадачаИнженера).Ячейки.Выполнено.Значение = Выборка.ВыполненоНаСегодня;
КонецЦикла;
КонецПроцедуры
Про параметры виртуальной таблицы уже сказали.
Еще у тебя абсолютно ненужный поиск по "ТаблицаЗадач". Его можно легко избежать.
При первом обходе оформлений строк в отдельном соответствии запоминаешь сопоставление задачи оформлению строки (или массиву оформлений строк).
А затем просто обходишь выборку данных запроса, получаешь из соответствия оформления нужных строк и оформляешь ячейки.
Ну и если одна и та же задача может соответствовать нескольким строкам, то и передавать нужно уникальный список. А лучше не список значений в запрос передавать, а всегда для этого использовать массив. Массив заметно "легче" списка значений.
На самом то деле, проблема в том, что ПриПолученииДанных несколько раз вызывается.
Но у нас документ, следовательно кол-во строк ограничено. Так что можно все расчеты повесить на процедуру ПриОткрытии, загонять результат в соответствие Задача - Выполнено, и в ПриПолученииДанных не запрос выполнять по нескольку раз, а пользоваться данными из соответствия.
На случай добавления строк - добавить расчет также на событие ПриОкончанииРедактирования.
Ну и соответствие, в котором результат расчета будет храниться, должно быть объявлено как переменная модуля.
Да толку в этих исследованиях никакого, на самом деле.
Для документа с ограниченным числом строк (26) вполне хватит.
По крайней мере, количество запросов становится вполне контролируемым.
План запроса при использовании оператора in показывает обход таблицы по записям, ни индексы ни ассоциации не работают т.е. только Loop, т.е. переберет все.
Всегда предпочтительней внутренне соединение Match, этого вы в виртуальной таблице не сможете сделать.
Я задаю отбор передачей параметра таблицей значений, и соединением с виртуальной таблицей, все равно виртуальная таблица вывалит тот же набор записей, что и для Loop внутри себя, а потом сделает Match, всегда быстрее. Если (35) использовать работает индекс т.е. Match.
А в вашем случает высокая селективность Ссылок, зачем виртуальная таблица? Легче сделать внутренне соединение с обычной таблицей по ссылкам. А потом уже ручками срез последних, тут много публикаций как это сделать.
а как часто меняется РегистрСведений.ВремяРаботыТехподдержки ? может проще вообще вынести получение среза в модуль с повторным возвратом испольуемых значений? тут гарантированно будет ускорение - причем ощутимое - все таки регист сведений довольно тормозной механизм
(42) caponid, сколько дней инженер делал задачу столько и будет записей.
(44) herfis, задача в регистре это измерение. Т.к. задача ставится одному сотруднику, то и срез только по задаче достаточен в условии. Можно дополнить еще условие по сотруднику, но это будет избыточно, но сути не поменяет.
(45) herfis, да сред и делает уникальные записи по задачам. Т.е. одна строка в списке есть 0 или 1 запись в срезе.
В моем случае оказалось самым производительным решение:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо = &РаботаПо) КАК ВремяРаботыТехподдержкиСрезПоследних";
Запрос.УстановитьПараметр("РаботаПо", ОформлениеСтроки.ДанныеСтроки.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Выполнено = Выборка.ВыполненоНаСегодня;
КонецЦикла;
ОформлениеСтроки.Ячейки.Выполнено.Значение = Выполнено;
КонецЦикла;
КонецПроцедуры
Показать
На втором месте:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Соответствие = Новый Соответствие;
МассивСсылок = Новый Массив;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
МассивСсылок.Добавить(ОформлениеСтроки.ДанныеСтроки.Ссылка);
Соответствие.Вставить(ОформлениеСтроки.ДанныеСтроки.Ссылка, ОформлениеСтроки);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ВремяРаботыТехподдержкиСрезПоследних.РаботаПо КАК ЗадачаИнженера,
| ВремяРаботыТехподдержкиСрезПоследних.ВыполненоНаСегодня
|ИЗ
| РегистрСведений.ВремяРаботыТехподдержки.СрезПоследних(, РаботаПо В (&СписокЗадач)) КАК ВремяРаботыТехподдержкиСрезПоследних";
Запрос.УстановитьПараметр("СписокЗадач", МассивСсылок);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Соответствие.Получить(Выборка.ЗадачаИнженера).Ячейки.Выполнено.Значение = Выборка.ВыполненоНаСегодня;
КонецЦикла;
КонецПроцедуры
Показать
Т.е. соответсвие будет оптимальнее врешении аналогичных задач. Где запрос будет в первом случае не настолько оптимален по производительности!
Обо всем чём нужно уже сказали, но вставлю пять копеек в подтверждение.
100% срез получайте сами. Соединение рулит.
Пачка ссылок лучше чем одна.
У вас речь о заметных полсекунде, а часто и 0.1 является заметной проблемой для комфортного юзания.
Кэш - очень неплохое решение. Но не кэш сеанса (повт.исп), а сделаете сами кэш на форме. Сохранять в кэш весь регистр - сомнительно при неизвестном размере реестра. Лучше накапливать в кэше полученные данные.