У нас есть справочник "Товры", в реквизите "Данные" которого сохраняется информация в виде двоичных данных. Сам реквизит имеет тип значения "ХранилищеЗначения". На следующем скриншоте представлена стркутура метаданных справочника.
Для прикрепления произвольного файла с диска в форме элемента реализована команда "ПрикрепитьФайл". Ее программный код представлен на следующем листинге:
&НаКлиенте Процедура ПрикрепитьФайл(Команда) // Обработчик команды на клиенте. Выбор файла // Диалог выбора файла с диска Режим = РежимДиалогаВыбораФайла.Открытие; ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим); ДиалогОткрытияФайла.ПолноеИмяФайла = ""; ДиалогОткрытияФайла.МножественныйВыбор = Ложь; ДиалогОткрытияФайла.Заголовок = "Выберите файлы"; Если ДиалогОткрытияФайла.Выбрать() Тогда ПутьКФайлу = ДиалогОткрытияФайла.ПолноеИмяФайла; // Получение двоичные данные файла ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу); // Передача двоичных данные на сервер ПрикрепитьФайлСервер(ДвоичныеДанные); Иначе Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!"""; Предупреждение(НСтр(Текст)); КонецЕсли; КонецПроцедуры &НаСервере Процедура ПрикрепитьФайлСервер(ДвоичныеДанные) // Обработчик на сервере записи файла в ИБ // Трансформируем объект формы в справочник-объект ОбъектТекущий = РеквизитФормыВЗначение("Объект"); // Присваиваем новое значение реквизиту "Данные" ОбъектТекущий.Данные = Новый ХранилищеЗначения(ДвоичныеДанные); // Сохраняем изменения ОбъектТекущий.Записать(); КонецПроцедуры
Если описать алгоритм в общих чертах, то сначала на клиенте выбирается файл с диска. Полученные двоичные данные файла отправляются на сервер, где записываются в информационную базу, а именно в реквизит "Данные" текущего элемента справочника.
В принципе все работает. При открытии элемента мы можем считывать эти данные по необходимости. Если, например, в реквизите сохранено изображение, то мы можетм получить его и вывести в поле формы. Такое решение имеет место быть, но в большинстве задач использовать реквизит с типом значения "ХранилищеЗначения" в справочниках и документах не оптимально. И вот почему...
Проведем несколько тестов на производительность. В тестах будут использоваться два элемента справочника "Товары" с прикрепленным файлом и без. Размер прикрепленного файла составляет 5 мегабайт.
Все тесты проводятся с помощью обработки "ПолучениеЭлемента" в тестовой конфигурации. Скачать данную конфигурацию Вы можете по ссылке в конце статьи.
Замерим время открытие элементов справочника "Товары". Для открытия элемента используется метод глобального контекста "ОткрытьЗначение()", в качестве параметра которому передается ссылка на элемент. Выполним замер времени открытия с помощью стандартного интруемента замера производительности. Результаты представлены на следующем скриншоте:
Как мы видим, время открытия элемента с прикрепленным файлом больше в 10 раз! Сделаем другой тест. Выполним метод "ПолучитьОбъект()" для ссылки на элемент справочника товары. Результат теста Вы можете видеть на следующем скриншоте.
Разница весьма существенная. Получение элемента без прикрепленного файла отрабатывает быстре в 194 раза!
Происходит это потому, что метод "ПолучитьОбъект()" получает все данные из реквизитов элемента справочника по ссылке. Соответственно, метод получает значения не только реквизитов "Код" и "Наименование", но и значение реквизита "Данные". Если в нем хранятся двоичные данные размером 5 мегабайт (как в нашем примере), то при получении объекта эти данные помещаются в оперативную память (как и остальные реквизиты) и затем передаются на клиентскую сторону. Именно получение данных из этого реквизита увеличивает время получения объекта элемента. Если же используется тонкий канал связи, то время открытия увеличится еще более значительно из-за передачи большого объема информации по сети.
Примечание: при выполнении метода "ОткрытьЗначение()" также сначала получается объект элемента справочника, а затем трансформируется в объект формы и передается на клиент (для управляемых форм). То есть, при открытии элемента по ссылке получение объекта также выполняется.
Проведем последний тест на время открытия и записи элемента справочника с прикрепленным файлом и без него. Результат представлен на следующем скриншоте.
Закономерный результат. Время получения и, затем, записи для элемента справочника с прикрепленным файлом оказалось в ~19 раз больше. Как было сказано выше, при получении объекта получаются значения всех его реквизитов, в том числе и реквизита "Данные" в котором сохранены 5 мегабайт информации. При записи элемента этот объем данных вновь записывается в информационную базу. Следовательно, хранение данных в реквизите справочника (или документа) с типом "ХранилищеЗначения" отрицательно влияет на производительность как при получении объекта, так и при помещении его в информационную базу.
Какой же способ решения задачи по хранению данных для объектов информационной базы наиболее правильный?
Если мы посмотрим на реализацию данного механизма в типовых конфигурациях, то увидим, что для объектов дополнительная информация хранится в отдельной таблице регистра сведений. Вот так, например, выглядит механизм присоединенных файлов в типовой конфигурациии "Управление торговлей" версии 11.
Справочник "Номенклатура" является владельцем для справочника "НоменклатураПрисоединенныеФайлы". Тот в свою очередь связан с регистрам сведений "ПрисоединенныеФайлы", измерение которого "ПрисоединенныйФайл" ссылается на его элемент. Таким образом, данные, прикрепляемые к объектам информационной базы, фактически хранится в таблице регистра сведений, на работу которого объекм хранимых данных в ресурсе практически не влияет. Промежуточный справочник "НоменклатураПрисоединенныеФайлы" необходим для хранения дополнительной информации для присоединенного файла, а тажке для поддержки обращения к присоединенному файлу по ссылке.
Все выше сказанное еще раз подтверждает огромное влияние на производительность правильно разработанной структуры метаданных конфигурации.
Тестовая конфигурация с примером из статьи: LINK.