Как улучшить производительность при проверке наличия изображений в 1С?

База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как улучшить производительность при проверке наличия изображений в 1С?

Просмотр 1 ветки ответов
  • Автор
    Записи
    • #38844
      Фото аватараOdineski
      Участник

        Мне нужно понять, есть ли возможность как то изменить код, чтобы увеличить скорость получения Наличия каринки. Сделал код, обратился к общему модулю (ПолучитьОсновноеИзображение(СсылкаНаОбъект)) чтобы он хотя бы 2 ичное значение принес. в 1с скат профессионале сижу.

        из общего модуля Управление Вложениями Клиент

        Функция ПолучитьОсновноеИзображение(СсылкаНаОбъект) Экспорт
        стрКаталогВложений=Константы.КаталогВложений.Получить();
        Если ПустаяСтрока(стрКаталогВложений) Тогда //Вложения хранятся в базе
        ОсновноеИзображение=СсылкаНаОбъект.ОсновноеИзображение.Получить();
        Иначе
        Если СсылкаНаОбъект.Пустая() Тогда Возврат Неопределено; КонецЕсли;
        ПолноеИмяФайла=стрКаталогВложений+»»+СсылкаНаОбъект.УникальныйИдентификатор()+»main_image»;
        ФайлИзображения=Новый Файл(ПолноеИмяФайла);
        ОсновноеИзображение=?(ФайлИзображения.Существует(), Новый ДвоичныеДанные(ПолноеИмяФайла), Неопределено);
        КонецЕсли;
        Возврат ?(ТипЗнч(ОсновноеИзображение)=Тип(«ДвоичныеДанные») И ОсновноеИзображение.Размер()>0, ОсновноеИзображение, Неопределено);
        КонецФункции

        Мой код
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        | ВТ_ОбъединениеТрехТабл.Номенклатура КАК Номенклатура,
        | ВТ_ОбъединениеТрехТабл.Артикул КАК Артикул,
        | ВТ_ОбъединениеТрехТабл.НачальныйОтстаток КАК НачальныйОтстаток,
        | ВТ_ОбъединениеТрехТабл.КонечныйОстаток КАК КонечныйОстаток,
        | ВТ_ОбъединениеТрехТабл.Потребность КАК Потребность,
        | ВТ_ОбъединениеТрехТабл.Резерв КАК Резерв,
        | ВТ_ОбъединениеТрехТабл.МинимальныйОстаток КАК МинимальныйОстаток,
        | ПартииТоваровНаСкладахОбороты.КоличествоПриход КАК Приобрели,
        | ПартииТоваровНаСкладахОбороты.КоличествоРасход КАК Продали
        |ИЗ
        | ВТ_ОбъединениеТрехТабл КАК ВТ_ОбъединениеТрехТабл
        | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Обороты(&ДатаНачало, &ДатаКонец, , ) КАК ПартииТоваровНаСкладахОбороты
        | ПО ВТ_ОбъединениеТрехТабл.Номенклатура.Ссылка = ПартииТоваровНаСкладахОбороты.Номенклатура.Ссылка»;

        Запрос.УстановитьПараметр(«ВведёнТекст», ВведёнТекст);
        Запрос.УстановитьПараметр(«ДатаКонец», ДатаКонец);
        Запрос.УстановитьПараметр(«ДатаНачало», ДатаНачало);
        Запрос.УстановитьПараметр(«НаименованиеЧасть», НаименованиеЧасть);
        Запрос.УстановитьПараметр(«Организация», Организация);
        Запрос.УстановитьПараметр(«Родитель», Родитель);
        Запрос.УстановитьПараметр(«Склад», Склад);

        //РезультатЗапроса = Запрос.Выполнить().Выгрузить();
        //РаботаКартинки(РезультатЗапроса);

        ТабЗначений = Новый ТаблицаЗначений;
        ТабЗначений.Колонки.Добавить(«Номенклатура»);
        ТабЗначений.Колонки.Добавить(«Артикул»);
        ТабЗначений.Колонки.Добавить(«МинимальныйОстаток»);
        ТабЗначений.Колонки.Добавить(«Потребность»);
        ТабЗначений.Колонки.Добавить(«Резерв»);
        ТабЗначений.Колонки.Добавить(«Приобрели»);
        ТабЗначений.Колонки.Добавить(«Продали»);
        ТабЗначений.Колонки.Добавить(«НачальныйОтстаток»);
        ТабЗначений.Колонки.Добавить(«КонечныйОстаток»);

        РезультатЗапроса = Запрос.Выполнить();
        ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        Стр = ТабЗначений.Добавить();
        Стр.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура ;
        Стр.Артикул = ВыборкаДетальныеЗаписи.Артикул ;
        Стр.МинимальныйОстаток = ВыборкаДетальныеЗаписи.МинимальныйОстаток ;
        Стр.Потребность = ВыборкаДетальныеЗаписи.Потребность ;
        Стр.Резерв = ВыборкаДетальныеЗаписи.Резерв ;
        Стр.Приобрели = ВыборкаДетальныеЗаписи.Приобрели ;
        Стр.Продали = ВыборкаДетальныеЗаписи.Продали ;
        Стр.НачальныйОтстаток = ВыборкаДетальныеЗаписи.НачальныйОтстаток ;
        Стр.КонечныйОстаток = ВыборкаДетальныеЗаписи.КонечныйОстаток ;
        КонецЦикла;

        Если ПолеВыбораФото = 1 Тогда

        Иначе

        ТЗнач = Новый ТаблицаЗначений;

        ТЗнач.Колонки.Добавить(«Номенклатура»);
        ТЗнач.Колонки.Добавить(«Артикул»);
        ТЗнач.Колонки.Добавить(«МинимальныйОстаток»);
        ТЗнач.Колонки.Добавить(«Потребность»);
        ТЗнач.Колонки.Добавить(«Резерв»);
        ТЗнач.Колонки.Добавить(«Приобрели»);
        ТЗнач.Колонки.Добавить(«Продали»);
        ТЗнач.Колонки.Добавить(«НачальныйОтстаток»);
        ТЗнач.Колонки.Добавить(«КонечныйОстаток»);

        Для Каждого СтЧасти Из ТабЗначений Цикл

        Номенклатура = СтЧасти.Номенклатура ;
        //КартинкаА = СтЧасти.Номенклатура.ОсновноеИзображение;
        //ПолКартинка = КартинкаА.Получить();
        Картинка = УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенклатура);

        //ЕстьКартинка = ЗначениеЗаполнено(Пр);
        //СсылкаНаФайл = ПолучитьНавигационнуюСсылку(Номенкла,»ОсновноеИзображение»);

        //Картинка = Пр.Получить();
        // Картинка = УправлениеВложениямиКлиент.ПолучитьОсновноеИзображение(Номенкла);
        // ЕстьКартинка = ЗначениеЗаполнено(Пр);
        // СсылкаНаФайл = ПолучитьНавигационнуюСсылку(Номенкла,»ОсновноеИзображение»);//ОсновноеИзображение ДанныеКартинки
        //

        //2 с фото
        Если ПолеВыбораФото = 2 Тогда
        Если ЗначениеЗаполнено(Картинка) Тогда
        Стр = ТЗнач.Добавить();
        Стр.Номенклатура = СтЧасти.Номенклатура ;
        Стр.Артикул = СтЧасти.Артикул ;
        Стр.МинимальныйОстаток = СтЧасти.МинимальныйОстаток ;
        Стр.Потребность = СтЧасти.Потребность ;
        Стр.Резерв = СтЧасти.Резерв ;
        Стр.Приобрели = СтЧасти.Приобрели ;
        Стр.Продали = СтЧасти.Продали ;
        Стр.НачальныйОтстаток = СтЧасти.НачальныйОтстаток ;
        Стр.КонечныйОстаток = СтЧасти.КонечныйОстаток ;

        Сообщить(«»);
        Иначе
        Сообщить(«»);
        КонецЕсли;
        Иначе
        Если Не ЗначениеЗаполнено(Картинка) Тогда
        Стр = ТЗнач.Добавить();
        Стр.Номенклатура = СтЧасти.Номенклатура ;
        Стр.Артикул = СтЧасти.Артикул ;
        Стр.МинимальныйОстаток = СтЧасти.МинимальныйОстаток ;
        Стр.Потребность = СтЧасти.Потребность ;
        Стр.Резерв = СтЧасти.Резерв ;
        Стр.Приобрели = СтЧасти.Приобрели ;
        Стр.Продали = СтЧасти.Продали ;
        Стр.НачальныйОтстаток = СтЧасти.НачальныйОтстаток ;
        Стр.КонечныйОстаток = СтЧасти.КонечныйОстаток ;
        Иначе

        КонецЕсли;

        КонецЕсли;

        КонецЦикла;

        ТабЗначений = ТЗнач;
        КонецЕсли;

        ВыводМакета(ТабЗначений);

        Значений около 9 тысяч

      • #38845
        bot_avaOdin — Одинэсник
        Участник

          Да, скорость можно увеличить в разы. Сейчас основная проблема в том, что для каждой из примерно 9000 номенклатур вы вызываете:

          А эта функция не просто проверяет наличие картинки. Она:

          1. Получает значение константы.
          2. Обращается к реквизиту ОсновноеИзображение.
          3. Вызывает .Получить(), то есть загружает двоичные данные картинки.
          4. Проверяет размер двоичных данных.
          5. При хранении во внешнем каталоге проверяет файл.
          6. При наличии файла загружает его через Новый ДвоичныеДанные(...).

          Для фильтрации вам сама картинка не нужна. Нужен только признак:

          ## 1. Исправьте общий модуль

          Создайте отдельную функцию, которая проверяет только наличие изображения и не загружает его содержимое.

          Например, в общем модуле УправлениеВложениямиСервер с флажком «Вызов сервера»:

          Ключевые отличия:

          вместо:

          И для внешнего хранения не выполняется:

          Это уже существенно ускорит проверку.

          Но если вызвать эту функцию из клиентского кода 9000 раз, всё равно получится до 9000 серверных вызовов. Поэтому лучше выполнять проверку пакетно.

          —

          # 2. Пакетная проверка картинок

          В том же серверном общем модуле создайте функцию, которая принимает массив номенклатуры и возвращает таблицу с признаками наличия.

          Теперь вместо 9000 обращений к серверу будет один вызов.

          —

          # 3. Как вызвать пакетную проверку в вашем коде

          После заполнения ТабЗначений сформируйте массив ссылок:

          Затем создайте соответствие для быстрого поиска признака:

          После этого фильтруйте таблицу без обращения к картинке:

          Здесь я предполагаю:

          означает «все товары»,

          означает «только с картинками»,

          означает «только без картинок».

          У вас сейчас для значения 1 стоит пустая ветка:

          Из-за этого лучше явно разделить режимы.

          —

          # 4. Еще лучше, если картинки хранятся в информационной базе

          Если в вашей базе КаталогВложений пустой, картинки хранятся в реквизите ОсновноеИзображение в базе. Тогда можно попробовать определить наличие прямо в запросе, не перебирая 9000 строк после выполнения запроса.

          В запрос добавляется поле:

          Например, начало запроса:

          Дальше при заполнении таблицы добавьте колонку:

          И заполнение:

          После этого фильтр будет очень простой:

          Однако этот вариант подходит только для хранения картинок в базе. Если КаталогВложений заполнен, SQL-запрос не знает, существует ли файл на диске. В таком случае используйте пакетную серверную проверку файлов.

          —

          # 5. Не вызывайте ПолучитьОсновноеИзображение для фильтрации

          Ваш текущий код:

          нужно заменить на:

          Но одиночный вызов всё равно будет медленнее пакетного. Оптимальный вариант для 9000 строк:

          1. Получить результат запроса.
          2. Одним вызовом проверить наличие изображений.
          3. Получить соответствие Номенклатура -> ЕстьИзображение.
          4. Отфильтровать таблицу.
          5. Только после этого выводить макет.

          —

          # 6. Уберите лишнее заполнение таблицы

          Сейчас вы вручную создаете ТабЗначений и переносите каждое поле:

          Если структура результата запроса вас устраивает, можно сразу выгрузить результат:

          То есть вместо:

          использовать:

          При этом в запросе должны быть только необходимые поля.

          Если используете вариант с признаком картинки в запросе, достаточно:

          А затем:

          ## Важное замечание по общему модулю

          Модуль с функцией проверки должен вызываться на сервере, особенно если указан внешний каталог вложений. Сервер 1С должен иметь доступ к каталогу:

          Если каталог находится на другом компьютере, сервер 1С должен видеть его по сетевому пути, например:

          А не по локальному пути пользователя:

          Иначе Файл.Существует() будет проверять диск сервера 1С, а не диск клиента.

          Самый быстрый вариант для вашей задачи:

          плюс определение признака ЕстьИзображение непосредственно в запросе, если изображения хранятся в базе. Если изображения лежат в каталоге, используйте одну пакетную серверную проверку, но не загружайте сами двоичные данные.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С