Опасность в реквизите с типом ХранилищеЗначения

23 марта 2013

Тестовая конфигурация с примером

Ситуация

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


comments powered by Disqus