База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как улучшить производительность при проверке наличия изображений в 1С?
- В этой теме 1 ответ, 2 участника, последнее обновление 9 минут назад сделано
Odin — Одинэсник.
-
АвторЗаписи
-
-
14 октября 2026 в 14:57 #38844
Мне нужно понять, есть ли возможность как то изменить код, чтобы увеличить скорость получения Наличия каринки. Сделал код, обратился к общему модулю (ПолучитьОсновноеИзображение(СсылкаНаОбъект)) чтобы он хотя бы 2 ичное значение принес. в 1с скат профессионале сижу.
из общего модуля Управление Вложениями Клиент
Функция ПолучитьОсновноеИзображение(СсылкаНаОбъект) Экспорт
стрКаталогВложений=Константы.КаталогВложений.Получить();
Если ПустаяСтрока(стрКаталогВложений) Тогда //Вложения хранятся в базе
ОсновноеИзображение=СсылкаНаОбъект.ОсновноеИзображение.Получить();
Иначе
Если СсылкаНаОбъект.Пустая() Тогда Возврат Неопределено; КонецЕсли;
ПолноеИмяФайла=стрКаталогВложений+»»+СсылкаНаОбъект.УникальныйИдентификатор()+»main_image»;
ФайлИзображения=Новый Файл(ПолноеИмяФайла);
ОсновноеИзображение=?(ФайлИзображения.Существует(), Новый ДвоичныеДанные(ПолноеИмяФайла), Неопределено);
КонецЕсли;
Возврат ?(ТипЗнч(ОсновноеИзображение)=Тип(«ДвоичныеДанные») И ОсновноеИзображение.Размер()>0, ОсновноеИзображение, Неопределено);
КонецФункцииМой код
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ОбъединениеТрехТабл.Номенклатура КАК Номенклатура,
| ВТ_ОбъединениеТрехТабл.Артикул КАК Артикул,
| ВТ_ОбъединениеТрехТабл.НачальныйОтстаток КАК НачальныйОтстаток,
| ВТ_ОбъединениеТрехТабл.КонечныйОстаток КАК КонечныйОстаток,
| ВТ_ОбъединениеТрехТабл.Потребность КАК Потребность,
| ВТ_ОбъединениеТрехТабл.Резерв КАК Резерв,
| ВТ_ОбъединениеТрехТабл.МинимальныйОстаток КАК МинимальныйОстаток,
| ПартииТоваровНаСкладахОбороты.КоличествоПриход КАК Приобрели,
| ПартииТоваровНаСкладахОбороты.КоличествоРасход КАК Продали
|ИЗ
| ВТ_ОбъединениеТрехТабл КАК ВТ_ОбъединениеТрехТабл
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Обороты(&ДатаНачало, &ДатаКонец, , ) КАК ПартииТоваровНаСкладахОбороты
| ПО ВТ_ОбъединениеТрехТабл.Номенклатура.Ссылка = ПартииТоваровНаСкладахОбороты.Номенклатура.Ссылка»;Запрос.УстановитьПараметр(«ВведёнТекст», ВведёнТекст);
Запрос.УстановитьПараметр(«ДатаКонец», ДатаКонец);
Запрос.УстановитьПараметр(«ДатаНачало», ДатаНачало);
Запрос.УстановитьПараметр(«НаименованиеЧасть», НаименованиеЧасть);
Запрос.УстановитьПараметр(«Организация», Организация);
Запрос.УстановитьПараметр(«Родитель», Родитель);
Запрос.УстановитьПараметр(«Склад», Склад);//РезультатЗапроса = Запрос.Выполнить().Выгрузить();
//РаботаКартинки(РезультатЗапроса);ТабЗначений = Новый ТаблицаЗначений;
ТабЗначений.Колонки.Добавить(«Номенклатура»);
ТабЗначений.Колонки.Добавить(«Артикул»);
ТабЗначений.Колонки.Добавить(«МинимальныйОстаток»);
ТабЗначений.Колонки.Добавить(«Потребность»);
ТабЗначений.Колонки.Добавить(«Резерв»);
ТабЗначений.Колонки.Добавить(«Приобрели»);
ТабЗначений.Колонки.Добавить(«Продали»);
ТабЗначений.Колонки.Добавить(«НачальныйОтстаток»);
ТабЗначений.Колонки.Добавить(«КонечныйОстаток»);РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Стр = ТабЗначений.Добавить();
Стр.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура ;
Стр.Артикул = ВыборкаДетальныеЗаписи.Артикул ;
Стр.МинимальныйОстаток = ВыборкаДетальныеЗаписи.МинимальныйОстаток ;
Стр.Потребность = ВыборкаДетальныеЗаписи.Потребность ;
Стр.Резерв = ВыборкаДетальныеЗаписи.Резерв ;
Стр.Приобрели = ВыборкаДетальныеЗаписи.Приобрели ;
Стр.Продали = ВыборкаДетальныеЗаписи.Продали ;
Стр.НачальныйОтстаток = ВыборкаДетальныеЗаписи.НачальныйОтстаток ;
Стр.КонечныйОстаток = ВыборкаДетальныеЗаписи.КонечныйОстаток ;
КонецЦикла;Если ПолеВыбораФото = 1 Тогда
Иначе
ТЗнач = Новый ТаблицаЗначений;
ТЗнач.Колонки.Добавить(«Номенклатура»);
ТЗнач.Колонки.Добавить(«Артикул»);
ТЗнач.Колонки.Добавить(«МинимальныйОстаток»);
ТЗнач.Колонки.Добавить(«Потребность»);
ТЗнач.Колонки.Добавить(«Резерв»);
ТЗнач.Колонки.Добавить(«Приобрели»);
ТЗнач.Колонки.Добавить(«Продали»);
ТЗнач.Колонки.Добавить(«НачальныйОтстаток»);
ТЗнач.Колонки.Добавить(«КонечныйОстаток»);Для Каждого СтЧасти Из ТабЗначений Цикл
Номенклатура = СтЧасти.Номенклатура ;
//КартинкаА = СтЧасти.Номенклатура.ОсновноеИзображение;
//ПолКартинка = КартинкаА.Получить();
Картинка = УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенклатура);//ЕстьКартинка = ЗначениеЗаполнено(Пр);
//СсылкаНаФайл = ПолучитьНавигационнуюСсылку(Номенкла,»ОсновноеИзображение»);//Картинка = Пр.Получить();
// Картинка = УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенкла);
// ЕстьКартинка = ЗначениеЗаполнено(Пр);
// СсылкаНаФайл = ПолучитьНавигационнуюСсылку(Номенкла,»ОсновноеИзображение»);//ОсновноеИзображение ДанныеКартинки
////2 с фото
Если ПолеВыбораФото = 2 Тогда
Если ЗначениеЗаполнено(Картинка) Тогда
Стр = ТЗнач.Добавить();
Стр.Номенклатура = СтЧасти.Номенклатура ;
Стр.Артикул = СтЧасти.Артикул ;
Стр.МинимальныйОстаток = СтЧасти.МинимальныйОстаток ;
Стр.Потребность = СтЧасти.Потребность ;
Стр.Резерв = СтЧасти.Резерв ;
Стр.Приобрели = СтЧасти.Приобрели ;
Стр.Продали = СтЧасти.Продали ;
Стр.НачальныйОтстаток = СтЧасти.НачальныйОтстаток ;
Стр.КонечныйОстаток = СтЧасти.КонечныйОстаток ;Сообщить(«»);
Иначе
Сообщить(«»);
КонецЕсли;
Иначе
Если Не ЗначениеЗаполнено(Картинка) Тогда
Стр = ТЗнач.Добавить();
Стр.Номенклатура = СтЧасти.Номенклатура ;
Стр.Артикул = СтЧасти.Артикул ;
Стр.МинимальныйОстаток = СтЧасти.МинимальныйОстаток ;
Стр.Потребность = СтЧасти.Потребность ;
Стр.Резерв = СтЧасти.Резерв ;
Стр.Приобрели = СтЧасти.Приобрели ;
Стр.Продали = СтЧасти.Продали ;
Стр.НачальныйОтстаток = СтЧасти.НачальныйОтстаток ;
Стр.КонечныйОстаток = СтЧасти.КонечныйОстаток ;
ИначеКонецЕсли;
КонецЕсли;
КонецЦикла;
ТабЗначений = ТЗнач;
КонецЕсли;ВыводМакета(ТабЗначений);
Значений около 9 тысяч
-
14 октября 2026 в 14:57 #38845
Да, скорость можно увеличить в разы. Сейчас основная проблема в том, что для каждой из примерно 9000 номенклатур вы вызываете:
1С (Код)1УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенклатура)А эта функция не просто проверяет наличие картинки. Она:
1. Получает значение константы.
2. Обращается к реквизитуОсновноеИзображение.
3. Вызывает.Получить(), то есть загружает двоичные данные картинки.
4. Проверяет размер двоичных данных.
5. При хранении во внешнем каталоге проверяет файл.
6. При наличии файла загружает его черезНовый ДвоичныеДанные(...).Для фильтрации вам сама картинка не нужна. Нужен только признак:
1С (Код)1Истина / Ложь## 1. Исправьте общий модуль
Создайте отдельную функцию, которая проверяет только наличие изображения и не загружает его содержимое.
Например, в общем модуле
УправлениеВложениямиСерверс флажком «Вызов сервера»:1С (Код)1234567891011121314151617181920212223242526272829Функция ЕстьОсновноеИзображение(СсылкаНаОбъект) ЭкспортЕсли Не ЗначениеЗаполнено(СсылкаНаОбъект) ТогдаВозврат Ложь;КонецЕсли;КаталогВложений = Константы.КаталогВложений.Получить();Если ПустаяСтрока(КаталогВложений) Тогда// Вложения хранятся в информационной базе.// Важно: не вызываем Получить().ХранилищеИзображения = СсылкаНаОбъект.ОсновноеИзображение;Возврат ЗначениеЗаполнено(ХранилищеИзображения);Иначе// Вложения хранятся во внешнем каталоге.ПолноеИмяФайла = КаталогВложений+ ""+ СсылкаНаОбъект.УникальныйИдентификатор()+ "main_image";Возврат Новый Файл(ПолноеИмяФайла).Существует();КонецЕсли;КонецФункцииКлючевые отличия:
1С (Код)1СсылкаНаОбъект.ОсновноеИзображениевместо:
1С (Код)1СсылкаНаОбъект.ОсновноеИзображение.Получить()И для внешнего хранения не выполняется:
1С (Код)1Новый ДвоичныеДанные(ПолноеИмяФайла)Это уже существенно ускорит проверку.
Но если вызвать эту функцию из клиентского кода 9000 раз, всё равно получится до 9000 серверных вызовов. Поэтому лучше выполнять проверку пакетно.
—
# 2. Пакетная проверка картинок
В том же серверном общем модуле создайте функцию, которая принимает массив номенклатуры и возвращает таблицу с признаками наличия.
1С (Код)12345678910111213141516171819202122232425262728293031323334353637383940414243Функция ПроверитьНаличиеИзображений(МассивНоменклатуры) ЭкспортРезультат = Новый ТаблицаЗначений;Результат.Колонки.Добавить("Номенклатура");Результат.Колонки.Добавить("ЕстьИзображение");КаталогВложений = Константы.КаталогВложений.Получить();Для Каждого Номенклатура Из МассивНоменклатуры ЦиклЕсли Не ЗначениеЗаполнено(Номенклатура) ТогдаПродолжить;КонецЕсли;ЕстьИзображение = Ложь;Если ПустаяСтрока(КаталогВложений) Тогда// Не загружаем двоичные данные.ЕстьИзображение = ЗначениеЗаполнено(Номенклатура.ОсновноеИзображение);ИначеПолноеИмяФайла = КаталогВложений+ ""+ Номенклатура.УникальныйИдентификатор()+ "main_image";ЕстьИзображение = Новый Файл(ПолноеИмяФайла).Существует();КонецЕсли;СтрокаРезультата = Результат.Добавить();СтрокаРезультата.Номенклатура = Номенклатура;СтрокаРезультата.ЕстьИзображение = ЕстьИзображение;КонецЦикла;Возврат Результат;КонецФункцииТеперь вместо 9000 обращений к серверу будет один вызов.
—
# 3. Как вызвать пакетную проверку в вашем коде
После заполнения
ТабЗначенийсформируйте массив ссылок:1С (Код)12345678910МассивНоменклатуры = Новый Массив;Для Каждого СтрокаТаблицы Из ТабЗначений ЦиклМассивНоменклатуры.Добавить(СтрокаТаблицы.Номенклатура);КонецЦикла;ТаблицаНаличияИзображений =УправлениеВложениямиСервер.ПроверитьНаличиеИзображений(МассивНоменклатуры);Затем создайте соответствие для быстрого поиска признака:
1С (Код)12345678СоответствиеКартинок = Новый Соответствие;Для Каждого СтрокаНаличия Из ТаблицаНаличияИзображений ЦиклСоответствиеКартинок.Вставить(СтрокаНаличия.Номенклатура,СтрокаНаличия.ЕстьИзображение);КонецЦикла;После этого фильтруйте таблицу без обращения к картинке:
1С (Код)123456789101112131415161718192021222324252627282930313233343536ТЗнач = Новый ТаблицаЗначений;ТЗнач.Колонки.Добавить("Номенклатура");ТЗнач.Колонки.Добавить("Артикул");ТЗнач.Колонки.Добавить("МинимальныйОстаток");ТЗнач.Колонки.Добавить("Потребность");ТЗнач.Колонки.Добавить("Резерв");ТЗнач.Колонки.Добавить("Приобрели");ТЗнач.Колонки.Добавить("Продали");ТЗнач.Колонки.Добавить("НачальныйОтстаток");ТЗнач.Колонки.Добавить("КонечныйОстаток");Для Каждого СтрокаТаблицы Из ТабЗначений ЦиклЕстьИзображение = Ложь;СоответствиеКартинок.Свойство(СтрокаТаблицы.Номенклатура,ЕстьИзображение);// ПолеВыбораФото = 2 - только с картинкамиЕсли ПолеВыбораФото = 2 И Не ЕстьИзображение ТогдаПродолжить;КонецЕсли;// ПолеВыбораФото = 3 - только без картинокЕсли ПолеВыбораФото = 3 И ЕстьИзображение ТогдаПродолжить;КонецЕсли;НоваяСтрока = ТЗнач.Добавить();ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТаблицы);КонецЦикла;ТабЗначений = ТЗнач;Здесь я предполагаю:
1С (Код)1ПолеВыбораФото = 1означает «все товары»,
1С (Код)1ПолеВыбораФото = 2означает «только с картинками»,
1С (Код)1ПолеВыбораФото = 3означает «только без картинок».
У вас сейчас для значения
1стоит пустая ветка:1С (Код)123Если ПолеВыбораФото = 1 ТогдаИначеИз-за этого лучше явно разделить режимы.
—
# 4. Еще лучше, если картинки хранятся в информационной базе
Если в вашей базе
КаталогВложенийпустой, картинки хранятся в реквизитеОсновноеИзображениев базе. Тогда можно попробовать определить наличие прямо в запросе, не перебирая 9000 строк после выполнения запроса.В запрос добавляется поле:
1С (Код)12345| ВЫБОР| КОГДА ВТ_ОбъединениеТрехТабл.Номенклатура.ОсновноеИзображение ЕСТЬ НЕ NULL| ТОГДА ИСТИНА| ИНАЧЕ ЛОЖЬ| КОНЕЦ КАК ЕстьИзображение,Например, начало запроса:
1С (Код)123456789101112131415161718192021222324|ВЫБРАТЬ| ВТ_ОбъединениеТрехТабл.Номенклатура КАК Номенклатура,| ВТ_ОбъединениеТрехТабл.Артикул КАК Артикул,| ВТ_ОбъединениеТрехТабл.НачальныйОтстаток КАК НачальныйОтстаток,| ВТ_ОбъединениеТрехТабл.КонечныйОстаток КАК КонечныйОстаток,| ВТ_ОбъединениеТрехТабл.Потребность КАК Потребность,| ВТ_ОбъединениеТрехТабл.Резерв КАК Резерв,| ВТ_ОбъединениеТрехТабл.МинимальныйОстаток КАК МинимальныйОстаток,| ПартииТоваровНаСкладахОбороты.КоличествоПриход КАК Приобрели,| ПартииТоваровНаСкладахОбороты.КоличествоРасход КАК Продали,| ВЫБОР| КОГДА ВТ_ОбъединениеТрехТабл.Номенклатура.ОсновноеИзображение ЕСТЬ НЕ NULL| ТОГДА ИСТИНА| ИНАЧЕ ЛОЖЬ| КОНЕЦ КАК ЕстьИзображение|ИЗ| ВТ_ОбъединениеТрехТабл КАК ВТ_ОбъединениеТрехТабл| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Обороты(| &ДатаНачало,| &ДатаКонец,| ,| ) КАК ПартииТоваровНаСкладахОбороты| ПО ВТ_ОбъединениеТрехТабл.Номенклатура.Ссылка =| ПартииТоваровНаСкладахОбороты.Номенклатура.СсылкаДальше при заполнении таблицы добавьте колонку:
1С (Код)1ТабЗначений.Колонки.Добавить("ЕстьИзображение");И заполнение:
1С (Код)12Стр.ЕстьИзображение =ВыборкаДетальныеЗаписи.ЕстьИзображение;После этого фильтр будет очень простой:
1С (Код)1234567Если ПолеВыбораФото = 2 И Не СтЧасти.ЕстьИзображение ТогдаПродолжить;КонецЕсли;Если ПолеВыбораФото = 3 И СтЧасти.ЕстьИзображение ТогдаПродолжить;КонецЕсли;Однако этот вариант подходит только для хранения картинок в базе. Если
КаталогВложенийзаполнен, SQL-запрос не знает, существует ли файл на диске. В таком случае используйте пакетную серверную проверку файлов.—
# 5. Не вызывайте
ПолучитьОсновноеИзображениедля фильтрацииВаш текущий код:
1С (Код)123Картинка = УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенклатура);Если ЗначениеЗаполнено(Картинка) Тогданужно заменить на:
1С (Код)12345ЕстьКартинка = УправлениеВложениямиСервер.ЕстьОсновноеИзображение(Номенклатура);Если ЕстьКартинка ТогдаНо одиночный вызов всё равно будет медленнее пакетного. Оптимальный вариант для 9000 строк:
1. Получить результат запроса.
2. Одним вызовом проверить наличие изображений.
3. Получить соответствиеНоменклатура -> ЕстьИзображение.
4. Отфильтровать таблицу.
5. Только после этого выводить макет.—
# 6. Уберите лишнее заполнение таблицы
Сейчас вы вручную создаете
ТабЗначенийи переносите каждое поле:1С (Код)123Стр.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;Стр.Артикул = ВыборкаДетальныеЗаписи.Артикул;...Если структура результата запроса вас устраивает, можно сразу выгрузить результат:
1С (Код)1ТабЗначений = Запрос.Выполнить().Выгрузить();То есть вместо:
1С (Код)123456РезультатЗапроса = Запрос.Выполнить();ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();Пока ВыборкаДетальныеЗаписи.Следующий() Цикл...КонецЦикла;использовать:
1С (Код)1ТабЗначений = Запрос.Выполнить().Выгрузить();При этом в запросе должны быть только необходимые поля.
Если используете вариант с признаком картинки в запросе, достаточно:
1С (Код)1ТабЗначений = Запрос.Выполнить().Выгрузить();А затем:
1С (Код)123456789101112131415161718192021222324Если ПолеВыбораФото <> 1 ТогдаТЗнач = ТабЗначений.СкопироватьКолонки();Для Каждого СтрокаТаблицы Из ТабЗначений ЦиклЕсли ПолеВыбораФото = 2И Не СтрокаТаблицы.ЕстьИзображение ТогдаПродолжить;КонецЕсли;Если ПолеВыбораФото = 3И СтрокаТаблицы.ЕстьИзображение ТогдаПродолжить;КонецЕсли;НоваяСтрока = ТЗнач.Добавить();ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТаблицы);КонецЦикла;ТабЗначений = ТЗнач;КонецЕсли;## Важное замечание по общему модулю
Модуль с функцией проверки должен вызываться на сервере, особенно если указан внешний каталог вложений. Сервер 1С должен иметь доступ к каталогу:
1С (Код)1КаталогВложенийЕсли каталог находится на другом компьютере, сервер 1С должен видеть его по сетевому пути, например:
1С (Код)1\СерверФайловВложенияА не по локальному пути пользователя:
1С (Код)1C:ВложенияИначе
Файл.Существует()будет проверять диск сервера 1С, а не диск клиента.Самый быстрый вариант для вашей задачи:
1С (Код)1ТабЗначений = Запрос.Выполнить().Выгрузить();плюс определение признака
ЕстьИзображениенепосредственно в запросе, если изображения хранятся в базе. Если изображения лежат в каталоге, используйте одну пакетную серверную проверку, но не загружайте сами двоичные данные.
-
-
АвторЗаписи
- Для ответа в этой теме необходимо авторизоваться.