1с управляемые формы хранилище значений

Ситуация

У нас есть справочник «Товры», в реквизите «Данные» которого сохраняется информация в виде двоичных данных. Сам реквизит имеет тип значения «ХранилищеЗначения». На следующем скриншоте представлена стркутура метаданных справочника.

Для прикрепления произвольного файла с диска в форме элемента реализована команда «ПрикрепитьФайл». Ее программный код представлен на следующем листинге:

Если описать алгоритм в общих чертах, то сначала на клиенте выбирается файл с диска. Полученные двоичные данные файла отправляются на сервер, где записываются в информационную базу, а именно в реквизит «Данные» текущего элемента справочника.

В принципе все работает. При открытии элемента мы можем считывать эти данные по необходимости. Если, например, в реквизите сохранено изображение, то мы можетм получить его и вывести в поле формы. Такое решение имеет место быть, но в большинстве задач использовать реквизит с типом значения «ХранилищеЗначения» в справочниках и документах не оптимально. И вот почему.

Влияние на производительность

Проведем несколько тестов на производительность. В тестах будут использоваться два элемента справочника «Товары» с прикрепленным файлом и без. Размер прикрепленного файла составляет 5 мегабайт.

Все тесты проводятся с помощью обработки «ПолучениеЭлемента» в тестовой конфигурации. Скачать данную конфигурацию Вы можете по ссылке в конце статьи.

Замерим время открытие элементов справочника «Товары». Для открытия элемента используется метод глобального контекста «ОткрытьЗначение()», в качестве параметра которому передается ссылка на элемент. Выполним замер времени открытия с помощью стандартного интруемента замера производительности. Результаты представлены на следующем скриншоте:

Как мы видим, время открытия элемента с прикрепленным файлом больше в 10 раз! Сделаем другой тест. Выполним метод «ПолучитьОбъект()» для ссылки на элемент справочника товары. Результат теста Вы можете видеть на следующем скриншоте.

Разница весьма существенная. Получение элемента без прикрепленного файла отрабатывает быстре в 194 раза!

Происходит это потому, что метод «ПолучитьОбъект()» получает все данные из реквизитов элемента справочника по ссылке. Соответственно, метод получает значения не только реквизитов «Код» и «Наименование», но и значение реквизита «Данные». Если в нем хранятся двоичные данные размером 5 мегабайт (как в нашем примере), то при получении объекта эти данные помещаются в оперативную память (как и остальные реквизиты) и затем передаются на клиентскую сторону. Именно получение данных из этого реквизита увеличивает время получения объекта элемента. Если же используется тонкий канал связи, то время открытия увеличится еще более значительно из-за передачи большого объема информации по сети.

Примечание: при выполнении метода «ОткрытьЗначение()» также сначала получается объект элемента справочника, а затем трансформируется в объект формы и передается на клиент (для управляемых форм). То есть, при открытии элемента по ссылке получение объекта также выполняется.

Проведем последний тест на время открытия и записи элемента справочника с прикрепленным файлом и без него. Результат представлен на следующем скриншоте.

Закономерный результат. Время получения и, затем, записи для элемента справочника с прикрепленным файлом оказалось в

19 раз больше. Как было сказано выше, при получении объекта получаются значения всех его реквизитов, в том числе и реквизита «Данные» в котором сохранены 5 мегабайт информации. При записи элемента этот объем данных вновь записывается в информационную базу. Следовательно, хранение данных в реквизите справочника (или документа) с типом «ХранилищеЗначения» отрицательно влияет на производительность как при получении объекта, так и при помещении его в информационную базу.

Какой же способ решения задачи по хранению данных для объектов информационной базы наиболее правильный?

Правильное решение

Если мы посмотрим на реализацию данного механизма в типовых конфигурациях, то увидим, что для объектов дополнительная информация хранится в отдельной таблице регистра сведений. Вот так, например, выглядит механизм присоединенных файлов в типовой конфигурациии «Управление торговлей» версии 11.

Справочник «Номенклатура» является владельцем для справочника «НоменклатураПрисоединенныеФайлы». Тот в свою очередь связан с регистрам сведений «ПрисоединенныеФайлы», измерение которого «ПрисоединенныйФайл» ссылается на его элемент. Таким образом, данные, прикрепляемые к объектам информационной базы, фактически хранится в таблице регистра сведений, на работу которого объекм хранимых данных в ресурсе практически не влияет. Промежуточный справочник «НоменклатураПрисоединенныеФайлы» необходим для хранения дополнительной информации для присоединенного файла, а тажке для поддержки обращения к присоединенному файлу по ссылке.

Все выше сказанное еще раз подтверждает огромное влияние на производительность правильно разработанной структуры метаданных конфигурации.

Тестовая конфигурация с примером из статьи: LINK .

ХранилищеЗначения (хранилище значений 1С) – это объект в языке 1С, который позволяет хранить в базе данных прочие значения, например картинки и файлы, структуры и таблицы значений.

Сначала мы создаем значение, например:
Знч = Новый ТаблицаЗначений();
Потом помещаем его в хранилище значений 1С:
Хранилище = Новый ХранилищеЗначения(Знч, Новый СжатиеДанных(9));
Сжатие данных в хранилище значений 1С с параметром «9» означает, что данные будут храниться в архивированном виде, с максимальной степенью сжатия.

Чтобы сохранить такое значение в базу данных, нужно создать объект конфигурации (справочник, документ и т.п.), у которого добавить реквизит с типом ХранилищеЗначения.
СправочникСсылка = Справочники.Хранилище.СоздатьЭлемент();
СправочникСсылка.ХранилищеЗначения = Хранилище;
СправочникСсылка.Записать();
Кроме хранения таких значений в базе данных, с помощью хранилища значений 1С, мы также можем сохранить такое значение в файл, например:
Настройки = Новый Структура();
Настройки.Вставить(«ПоУмолчанию», Истина);
Настройки.Вставить(«Наименование», «Наименование1»);

Хранилище = Новый ХранилищеЗначения(Настройки, Новый СжатиеДанных(9));
ЗначениеВФайл(«C:», Хранилище);

Пример – сохранение значения из файла
//Значение — картинка из файла
Файл = Новый Картинка(«C:ФайлКартинки.jpg»);
Хранилище = Новый ХранилищеЗначения(Файл, Новый СжатиеДанных(9));

//Значение — произвольный файл
Файл = Новый ДвоичныеДанные(«C:ИсполняемыйФайл.exe»);
Хранилище = Новый ХранилищеЗначения(Файл, Новый СжатиеДанных(9));

//Значение — текстовый файл
Файл = Новый ЧтениеТекста(«C:ТекстовыйФайл.txt»);
ТекстовыеДанные = Файл.Прочитать();
Хранилище = Новый ХранилищеЗначения(ТекстовыеДанные, Новый СжатиеДанных(9));
Значение, помещенное в хранилище значений 1С нельзя использовать, пока оно там находится. Чтобы работать с ним, его нужно «распаковать» обратно, например:
Знч = Хранилище.Получить();
Если Знч = Неопределено Тогда
Сообщить(«Ошибка получения значения из хранилища»);
КонецЕсли;

&НаСервере Процедура УдалитьДанныеХЗНаСервере() ЭлементСправочника = РеквизитФормыВЗначение(«Объект»); ЭлементСправочника.ХранилищеЗначения = Новый ХранилищеЗначения(Неопределено); ЭлементСправочника.Записать(); ЗначениеВРеквизитФормы(ЭлементСправочника, «Объект»); КонецПроцедуры

Оцените статью