Каталог решений - Хранение файлов — как уменьшить размер базы данных

Хранение файлов — как уменьшить размер базы данных

Хранение файлов — как уменьшить размер базы данных

В наличии

Хранение файлов в базе 1С можно оптимизировать для уменьшения размера хранимых данных.

Категория:

Описание

Очень часто, в базах 1С организуют хранилище файлов, что удобно. Например, удобно хранить переписку по электронной почте. И вот, представьте, вы берете к-нить картинку и отправляете 8 своим коллегам, с точки зрения обычного хранения данных, в вашей БД, сохранится 9 копий данной картинки, а если ваши коллеги начнут отвечать на письмо, то и больше.

Вот так это выглядит;одинаковые файлы, записываются несколько раз:

 

Хранение файлов в базе 1С можно оптимизировать для уменьшения размера хранимых данных. В этом нам поможет теория, что ХЕШ-функции способны определить изменения даже одного бита в файле.

1С поддерживает следующие алгоритмы, но можно использовать и внешние вызовы, для получения ХЕШа:

  • CRC32 (CRC32)
  • MD5 (MD5)
  • SHA1 (SHA1)
  • SHA256 (SHA256)

Основная идея в том, что прежде чем записать в БД файл, проверить — существует ли точно такой же файл или нет? Если существует, то записывать его нет необходимости, и можно сохранить только необходимые реквизиты — имя файла, ссылка на объект и т.д.

Для ускорения перебора файлов, мы сначала ищем их по размеру (число) потом уже по ХЕШу. Для чего у нас есть регистр:

 

Если файл не найден, мы его записываем в хранилище значений, если найден, то записываем ссылку на него, уже в другом регистре:

 

 

Я провел эксперимент, взял БД с обычным хранением файлов и БД с переделанным под описанный выше алгоритм хранением. После чего, в 2 БД были загружены письма за 1 год. Результат — база данных стала более чем в 3 раза меньше:

 

 

Для "усиления" надежности, можно использовать несколько ХЕШ-функций. Падения быстродействия при загрузке почты, я не заметил.

Немного кода:

&НаСервере
Функция ПолучитьРазмерФайлаИХешМД5(_ХранилищеЗначения) Экспорт
	Структура = новый Структура;
	
	ДД = _ХранилищеЗначения.Получить();
	РазмерФайла = ДД.Размер();
	
	Хэш = Новый ХешированиеДанных(ХешФункция.MD5);
	Хэш.Добавить(ДД);
	МД5Двоичный = Хэш.ХешСумма;
	Результат = ПолучитьHexСтрокуИзДвоичныхДанных(МД5Двоичный); 
	ХешМД5 = Результат; 	

	Структура.Вставить("РазмерФайла",	РазмерФайла);
	Структура.Вставить("ХешМД5", 		ХешМД5);

	Возврат Структура;
КонецФункции

&НаСервере
Процедура ЗаполнитьВложения(_Файлы, ИмяВложения, ИнтернетПочтовоеСообщение, _Владелец) Экспорт
	
	Для Каждого ИнтернетПочтовоеВложение Из ИнтернетПочтовоеСообщение.Вложения Цикл
		
		ИмяВложения = ИнтернетПочтовоеВложение.Имя;
		
		Если ТипЗнч(ИнтернетПочтовоеВложение.Данные) = Тип("ДвоичныеДанные") Тогда
			
			СтруктураФайла = Новый Структура;
			 
			СтруктураФайла.Вставить("ИмяФайла",				ИмяВложения);
			СтруктураФайла.Вставить("Идентификатор",		ИнтернетПочтовоеВложение.Идентификатор);
			СтруктураФайла.Вставить("ПутьКФайлу",			"");
			СтруктураФайла.Вставить("ХранилищеЗначения"	,	Новый ХранилищеЗначения(ИнтернетПочтовоеВложение.Данные, Новый СжатиеДанных()));
			СтруктураФайла.Вставить("СпособКодирования",	Строка(ИнтернетПочтовоеВложение.СпособКодирования));
			СтруктураФайла.Вставить("ТипСодержимого",		ИнтернетПочтовоеВложение.ТипСодержимого);

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

&НаСервере
Функция СоздатьФайл(_Владелец, _СтруктураФайла) Экспорт

	ИмяФайла			= _СтруктураФайла.ИмяФайла;	
	Идентификатор		= _СтруктураФайла.Идентификатор;
	ПутьКФайлу			= _СтруктураФайла.ПутьКФайлу;
	ХранилищеЗначения	= _СтруктураФайла.ХранилищеЗначения;
	СпособКодирования	= _СтруктураФайла.СпособКодирования;
	ТипСодержимого		= _СтруктураФайла.ТипСодержимого;

	СтруктураФайла		= ПолучитьРазмерФайлаИХешМД5(ХранилищеЗначения);	
	ФайлСсылка			= НайтиФайлПоРазмеруФайлаИХешуМД5(СтруктураФайла.РазмерФайла, СтруктураФайла.ХешМД5);	
	
	Если ФайлСсылка = неопределено Тогда 
		
		Файл = Справочники.Файлы.СоздатьЭлемент();	
		Файл.Наименование			= ИмяФайла;
		Файл.ДанныеФайла 			= ХранилищеЗначения;
		
		Файл.Записать();
		
		ФайлСсылка = Файл.Ссылка;
	КонецЕсли;
	
	Регистр = РегистрыСведений.Регистр_ВладельцыФайлов.СоздатьНаборЗаписей();	
	Регистр.Отбор.Источник.Установить(ФайлСсылка);		
	Регистр.Отбор.ВладелецФайла.Установить(_Владелец);
	
	Регистр.Прочитать();
	
	Если Регистр.Количество() = 0 Тогда
		ЗаписьРегистра	= Регистр.Добавить();
		
		ЗаписьРегистра.Источник			= ФайлСсылка;
		ЗаписьРегистра.ВладелецФайла	= _Владелец;    

	ИначеЕсли Регистр.Количество() > 1 Тогда
		ВызватьИсключение "В регистре Регистр_ВладельцыФайлов для (" + Строка(ФайлСсылка) + ") найдено несколько одинаковых значений. Сообщите разработчику. Сделайте скриншот вводимых данных.";
	Иначе
		ЗаписьРегистра = Регистр[0];
	КонецЕсли;
	
	ЗаписьРегистра.ИмяФайла				= ИмяФайла;
	ЗаписьРегистра.Идентификатор		= Идентификатор;
	ЗаписьРегистра.ПутьКФайлу			= ПутьКФайлу;
	ЗаписьРегистра.СпособКодирования	= СпособКодирования;
	ЗаписьРегистра.ТипСодержимого		= ТипСодержимого;	
	
	Регистр.Записать();			
	
	Возврат ФайлСсылка; 
	
КонецФункции


 

has been added to your cart:
Оформление заказа