Как хранить структуру 1с
Объект "ХранилищеЗначения" известен в 1С, начиная с 8.0 и, казалось бы, прост, понятен, изучен вдоль и поперёк. Но иногда возникают вопросы, касающиеся работы с хранилищем, и данная публикация (по сути, краткий антисклерозник) призвана зафиксировать ответы на некоторые из них.
Хранилище значения (далее ХЗ) представляет собой данные, полученные кодированием и, при необходимости, сжатием входных данных с помощью 32-х битного алгоритма // из строки в ХЗ хз=XMLЗначение(Тип("ХранилищеЗначения"),ИсходнаяСтрокаBase64); // из ХЗ в строку ИтоговаяСтрокаBase64=XMLСтрока(ХЗ);
Важно понимать, что ХЗ это не значение, а указатель на область памяти. Они всегда разные, поэтому ни сравнение, ни поиск, ни отбор (в т.ч. в запросах) применять нельзя. Указатель равен сам себе лишь в рамках конкретного оператора-конструктора (и, кстати, в этом случае по нему работает, например, поиск в универсальных коллекциях). Так, например, если "А=хз; Б=А;", то А будет равно Б. А для сравнения именно значений следует действовать так (причём это не будет распаковкой как "расжатием"):
и это не зависит от наличия и степени сжатия в их конструкторах. Кстати, после применения конструктора определить степень сжатия можно лишь преобразованием в двоичные данные и анализом первых битов потока.
Так вот, размер "как есть" мы можем узнать, либо создав объект метаданных (например, справочник с единственным реквизитом типа ХЗ) и получив размер таблицы методом ПолучитьРазмерДанныхБазыДанных, либо опосредованно, через строку и двоичные данные (учитывая неизбежно прибавляемое), так:
Это не годится для абсолютных замеров (так, один символ латиницы, т.е. по идее 1 байт, и символ кириллицы, 2 байта, дают одинаковые 32 байта на выходе), но годится для относительных прикидок. Так, вызов без прямого указания "СжатиеДанных" всегда даёт значение большего (и иногда существенно большего, в разы) размера, чем с любым сжатием. На малых размерах сжатие не даёт заметного эффекта при любом аргументе. В СП сказано, что аргумент по умолчанию для объекта "СжатиеДанных" равен 1, но сжатие без его указания и с явным указанием даёт разные размеры, до десятков и сотен байт. На средних объектах (например, строки 500-1000 символов) сжатие со степенью выше 3-4 даёт примерно одинаковые итоговые размеры, т.е. эффективность одинаковая. Наряду с этим, в ряде старых релизов конструктор без сжатия даёт меньший итоговый размер.
Деструкция этого указателя тоже имеет нюансы.
В таблицах/деревьях значений с явно объявленной колонкой может использоваться везде, кроме запроса (не помещается в ВТ), не воспринимается как аргумент запроса, даже как &ПараметрТипаХЗ в секции "ВЫБРАТЬ". Что, учитывая известное про СУБД, не вполне логично.
При копировании объекта с реквизитами, содержащими ХЗ, ни интерфейсно, ни программно, эти значения НЕ наследуются, не копируются.
Если некое значение, упакованное в ХЗ, подпадает под RLS, то логика следующая - платформа всегда вначале выполняет неявную распаковку, либо рассматривает сделанную в коде явную; а затем накладывает ограничение, так что RLS применится именно для уже распакованного значения, спровоцировать тут ошибку ни разу не удалось.
Из интересных публикаций рекомендую эту.
Поскольку в современных метаданных конфигураций реквизит типа ХЗ где-нибудь точно наличествует, а также фигурирует в коде, то вопрос занимаемого им места актуален. В связи с этим было бы интересно исследовать рост места, занимаемого таблицей, состоящей исключительно из ХЗ, а также сравнить эффективность работы "СжатиеДанных" и основанного на том же Deflation объекта "ЗаписьZipФайла", пробуя разные значения УровеньСжатияZIP (естественно, при МетодСжатияZIP = "Сжатие").
Возможно, этот привычный и вроде бы простой объект, Хранилище значения, преподнесёт (особенно на больших данных и нагрузках) ещё некоторые удивительные сюрпризы.
Хранилище значений в 1С 8.3 это объект, который позволяет хранить в сериализованном виде почти любые типы данных (включая двоичные). Хранение происходит в самой базе данных (файле 1Cv8.1CD или на SQL-сервере в таблицах). Соответственно при выгрузки конфигурации, данные используемые хранилищем значений будут включены в архив базы (резервную копию). С помощью этого объекта можно хранить такие данные как: файлы, картинки (фотографии), внешние обработки, таблицы значений, структуры. Важно понимать, что хранение данных в таком виде будет существенно замедлять работу базы данных. Поэтому данную технологию хранения рекомендуется использовать в крайних случаях, если отсутствует альтернатива решения для имеющейся задачи.
// *** 1.Пример (Таблица значений):
ЗначенияТЗ = Новый ТаблицаЗначений (); // Создание значения "ТЗ"
// Вставка в хранилище значений
Хранилище_Зн = Новый ХранилищеЗначения ( ЗначенияТЗ , Новый СжатиеДанных ( 9 )); // "9" - макс.степень сжатия
// Сохранение значения в реквизит объекта конфигурации (тип: ХранилищеЗначения)
СправочникСтранаСсылка = Справочники . Страны . НайтиПоНаименованию ( "Испания" );
СправочникСтранаСсылка . ХранилищеЗначения = Хранилище_Зн ;
СправочникСтранаСсылка . Записать ();
// *** 2.Пример (Табличный документ):
ЗначенияТабДок =Новый ТабличныйДокумент ;
ЗначенияТабДок . Вывести ( ЭлементыФормы . ПолеТабличногоДокумента1 );
Хранилище_ТабДок =Новый ХранилищеЗначения ( ЗначенияТабДок );
// *** 3.Пример (Структура):
ЗначенияСтр = Новый Структура (); // Создание значения "Структура"
ЗначенияСтр . Вставить ( "Код" , "34" );
ЗначенияСтр . Вставить ( "Наименование" , "Испания" );
ЗначенияСтр . Вставить ( "Описание" , "Европейская страна, расположенная на Пиренейском полуострове" );
ЗначенияСтр . Вставить ( "Население" , 46600000 );
// Вставка в хранилище значений
Хранилище_Стр = Новый ХранилищеЗначения ( ЗначенияСтр , Новый СжатиеДанных ( 9 )); // "9" - макс.степень сжатия
ЗначениеВФайл ( "D:\import\" , Хранилище_Стр ); // Сохранение значения в файл
// *** 4.Пример (Любой файл) :
ФайлДвоичныеДанные = Новый ДвоичныеДанные ( "D:\import\КлиентБанк_РБ.exe" );
Хранилище_Файл = Новый ХранилищеЗначения ( ФайлДвоичныеДанные , Новый СжатиеДанных ( 0 )); // "0" - без сжатия
// *** 5.Пример (Файл картинка) :
ФайлФото = Новый Картинка ( "D:\import\ФотоСотрудника.jpg" );
Хранилище_Фото = Новый ХранилищеЗначения ( ФайлФото , Новый СжатиеДанных ( 5 )); // "5" - средн.степень сжатия
// *** 6.Пример (Текстовый файл) :
ФайлТекст = Новый ЧтениеТекста ( "D:\import\Война_и_мир.txt" );
ТекстИзФайла = ФайлТекст . Прочитать ();
Хранилище_Текст = Новый ХранилищеЗначения ( ТекстИзФайла , Новый СжатиеДанных ( 1 )); // "1" - мин.степень сжатия
// *** 7.Пример (Отчет/обработка 1С) :
Хранилище_Epf = Новый ХранилищеЗначения (Новый ДвоичныеДанные ( "D:\import\Otchet_realizacija_2020.epf" , СтепеньСжатия ));
// Двоичные данные можно восстановить из хранилища значения методом Получить и записать в файл методом Записать()
Если ТипЗнч ( РеквизитХранилище ) = Тип ( "ДвоичныеДанные" ) Тогда
// Хранилище.Получить()<>Неопределено Тогда // Процедура извлекает данные из хранилища (требует времени)
// Для больших объемов данных рекомендуется использовать доп.реквизит (Например: Булево) Содержит данные - Истина
ДанныеХранилища = РеквизитХранилище . Получить ();
Если ДанныеХранилища = Неопределено Тогда
Сообщить ( "Ошибка получения данных из хранилища значений 1С" );
КонецЕсли;
ДанныеХранилища . Записать ( ИмяФайла ); // Записываем восстановленые данные в файл
// Восстановление Табличного документа
ЭлементыФормы . ПолеТабличногоДокумента1 . Вывести ( ДанныеХранилища );
// Восстановление и запуск Отчета/обработки 1С
ИмяФайла_Epf = "D:\import\Otchet_realizacija_2020.epf" ;
ДвоичныеДанные = РеквизитХранилище . Получить ();
ДвоичныеДанные . Записать ( ИмяФайла_Epf );
Epf = ВнешниеОбработки . Создать ( ИмяФайла_Epf );
Epf . ПолучитьФорму (). Открыть ();
Иначе
ДанныеХранилища = РеквизитХранилище ;
КонецЕсли;
Тип Хранилище значения может быть назначен реквизиту справочника, документа, ресурсу регистра сведений и т.д.
Восьмерка поддерживает сжатие данных, помещаемых в хранилище:
Если это были ДвоичныеДанные, то их можно восстановить из хранилища значения методом Получить и записать в файл методом Записать().
Чтобы очистить поле типа Хранилище значения, нужно присвоить ему Неопределено:
Код 1C v 8.х
Если в Хранилище значений содержались какие-то ссылки, то они не будут контролироваться при контроле ссылочной целостности (операция Удаление помеченных объектов или метод НайтиПоСсылкам).
К сожалению, 1С не содержит встроенных методов для проверки того, заполнено хранилище или нет.
Такой вариант не работает:
Код 1C v 8.х
Работает только такой вариант:
Код 1C v 8.х
Но он требует затрат времени на извлечение данных из хранилища.
Поэтому, если это критично, нужно заводить еще один флаг, который указывает, содержит ли хранилище значение.
Похожие FAQ
Еще в этой же категории
Работа с изображениями (картинками) в интерфейсе Такси 12
Рассмотрим алгоритм работы с файлами и картинками в новом интерфейсе 1С:Предприятие 8.3 "Такси". Во-первых, почему я решил написать эту статью: Новая концепция 1С - отказ от модальных окон, следовательно все методы и объекты, которые порождали о Загрузка картинок в базу 1С (сохранение в хранилище значений) 8
В теме форма: v8: Получение данных из ХралищаЗначений Bell в управляемом интерфейсе пробует сохранить выбранные картинки в базу 1С, но возникли сложности с сохранением в хранилище значений. как пример Bell приложил CF файл с мини конфигурацией, Выбрать файл и записать в реквизит типа Хранилище значений 2
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); Диалог.Заголовок = " Выберите файл" ; Диалог.ПолноеИмяФайла = " " ; Фильтр = " DOC (*.doc)|*.doc|DOCX (*.docx)|*.docx" ; Диалог.Фильтр = Фильтр; //Диалог.МножественныйВыбор Как очистить значение, имеющее тип «Хранилище значения»? 1
РеквизитХранилище = Неопределено; Сохранить файл на диске полученный из реквизита типа хранилище значения 1
// Параметры // Хранилище – ХранилищеЗначения, которое содержит объект типа // ДвоичныеДанные с файлом для записи на диск. // ИмяФайла – Строка, содержащая полное имя файла. // ТолькоЧтение – Булево, признак установки Посмотреть все в категории Работа с Хранилищем Значений
Тип Хранилище значения может быть назначен реквизиту справочника, документа, ресурсу регистра сведений и т.д.
Восьмерка поддерживает сжатие данных, помещаемых в хранилище:
Если это были ДвоичныеДанные, то их можно восстановить из хранилища значения методом Получить и записать в файл методом Записать().
Чтобы очистить поле типа Хранилище значения, нужно присвоить ему Неопределено:
Код 1C v 8.х
Если в Хранилище значений содержались какие-то ссылки, то они не будут контролироваться при контроле ссылочной целостности (операция Удаление помеченных объектов или метод НайтиПоСсылкам).
К сожалению, 1С не содержит встроенных методов для проверки того, заполнено хранилище или нет.
Такой вариант не работает:
Код 1C v 8.х
Работает только такой вариант:
Код 1C v 8.х
Но он требует затрат времени на извлечение данных из хранилища.
Поэтому, если это критично, нужно заводить еще один флаг, который указывает, содержит ли хранилище значение.
Похожие FAQ
17 правил для составления оптимального ЗАПРОСа к данным базы 1С 44
Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос . Создается этот объект вызовом конструкции Новый Запрос . Запрос удобно использовать, когда требуется получ 1C: Enterprise Development Tools 50
И вот случилось долгожданное: Вышел 1C: Enterprise Development Tools - это среда для разработки конфигурации в IDE Eclipse. С сайта 1С: « 1C:Enterprise Development Tools » – это инструмент нового поколения для разработчиков бизнес-приложений систем Google maps : вывод точек на карту и режим панорамы 7
В отличие от яндекс карт в GMaps можно использовать панорамы - за что им большой плюс! Надеюсь в яндексе прочитают этот пост и тоже когда-нибудь это сделают! Для клиента нужно было сделать вывод объектов на карту С возможностью просмотра панора Microsoft SQL Server Native Client Добавление значения в столбец "datetime" привело к переполнению 2
При формировании отчета на СКД получили ошибку: Microsoft SQL Server Native Client 11.0: Добавление значения в столбец "datetime" привело к переполнению Подробнее текст такой: . по причине: Ошибка компоновки данных по причине: Ошибка получени PostgreSQL: установка, настройка, обслуживание 11
PostgreSQL напрямую "из коробки" применяться для использования с 1С Предприятем не может. Необходима именно адаптированная версия от 1С, превращающая PostgreSQL в блокировочник, причем нужно понимать, что блокировки будут накладываться на всю таблиц Посмотреть все результаты поиска похожих
Еще в этой же категории
Работа с изображениями (картинками) в интерфейсе Такси 12
Рассмотрим алгоритм работы с файлами и картинками в новом интерфейсе 1С:Предприятие 8.3 "Такси". Во-первых, почему я решил написать эту статью: Новая концепция 1С - отказ от модальных окон, следовательно все методы и объекты, которые порождали о Загрузка картинок в базу 1С (сохранение в хранилище значений) 8
В теме форма: v8: Получение данных из ХралищаЗначений Bell в управляемом интерфейсе пробует сохранить выбранные картинки в базу 1С, но возникли сложности с сохранением в хранилище значений. как пример Bell приложил CF файл с мини конфигурацией, Как очистить ХранилищеЗначение в Управляемой форме 1
НаСервере Процедура УдалитьДанныеХЗНаСервере() ЭлементСправочника = РеквизитФормыВЗначение("Объект"); ЭлементСправочника.ХранилищеЗначения = Новый ХранилищеЗначения(Неопределено); ЭлементСправочника.Записать(); ЗначениеВРеквизитФормы(ЭлементСправо Посмотреть все в категории Работа с Хранилищем Значений
Тип Хранилище значения может быть назначен реквизиту справочника, документа, ресурсу регистра сведений и т.д.
Восьмерка поддерживает сжатие данных, помещаемых в хранилище:
Если это были ДвоичныеДанные, то их можно восстановить из хранилища значения методом Получить и записать в файл методом Записать().
Чтобы очистить поле типа Хранилище значения, нужно присвоить ему Неопределено:
Код 1C v 8.х
Если в Хранилище значений содержались какие-то ссылки, то они не будут контролироваться при контроле ссылочной целостности (операция Удаление помеченных объектов или метод НайтиПоСсылкам).
К сожалению, 1С не содержит встроенных методов для проверки того, заполнено хранилище или нет.
Такой вариант не работает:
Код 1C v 8.х
Работает только такой вариант:
Код 1C v 8.х
Но он требует затрат времени на извлечение данных из хранилища.
Поэтому, если это критично, нужно заводить еще один флаг, который указывает, содержит ли хранилище значение.
Похожие FAQ
Еще в этой же категории
Выбрать файл и записать в реквизит типа Хранилище значений 2
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); Диалог.Заголовок = " Выберите файл" ; Диалог.ПолноеИмяФайла = " " ; Фильтр = " DOC (*.doc)|*.doc|DOCX (*.docx)|*.docx" ; Диалог.Фильтр = Фильтр; //Диалог.МножественныйВыбор Как очистить значение, имеющее тип «Хранилище значения»? 1
РеквизитХранилище = Неопределено; Сохранить файл на диске полученный из реквизита типа хранилище значения 1
// Параметры // Хранилище – ХранилищеЗначения, которое содержит объект типа // ДвоичныеДанные с файлом для записи на диск. // ИмяФайла – Строка, содержащая полное имя файла. // ТолькоЧтение – Булево, признак установки Создать, заменить, записать файл в Хранилище Значения 1
Функция СоздатьФайлВХранилище(ЛокПолноеИмяФайла,ЛокНаименованиеЭлемента)Экспорт Попытка ЛокХранилище = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ЛокПолноеИмяФайла)); Исключение Возврат Null; КонецПопытки; ЛокСправочникХЗН = Справочники.Хран Как проверить тип значения, помещенного в реквизит имеющий тип 0
Значение = Фотография.Получить(); Если Значение Неопределено Тогда Если ТипЗнч(Значение) = Тип(" Строка" ) Тогда // Обработать строку. ИначеЕсли ТипЗнч(Значение) = Тип(" Картинка" ) Тогда // Обработать картинку. Сообщить(" Картинка" ); Посмотреть все в категории Работа с Хранилищем Значений
Читайте также: