При разработке конфигураций на платформе 1С программисты часто сталкиваются с необходимостью хранения сложных структур данных, настроек или двоичных файлов (картинок, документов) непосредственно в базе данных. Одним из удобных инструментов для этого является объект ХранилищеЗначения, используемый в качестве типа данных для константы. Однако работа с ним имеет ряд специфических особенностей, особенно когда речь заходит об извлечении отдельных элементов из сохраненного массива или структуры.
В этой статье мы подробно разберем, как программно обращаться к константам с типом ХранилищеЗначения, выясним, почему нельзя прочитать данные «частично», и проанализируем влияние такого подхода на производительность системы.
Прежде всего, разберем природу самого объекта. ХранилищеЗначения — это специальный контейнер, который при записи сериализует переданные в него данные. Сериализация превращает привычные нам объекты (массивы, структуры, таблицы значений) в специфический бинарный поток, который к тому же сжимается платформой для экономии места. С точки зрения базы данных (SQL), это просто поле типа VARBINARY или IMAGE — своего рода «черный ящик».
Когда вы помещаете в константу структуру из десяти элементов, 1С не создает десять полей в таблице базы данных. Она упаковывает всю структуру в один бинарный блок. Именно поэтому ответ на вопрос «можно ли получить определенное значение, а не все» — отрицательный. Чтобы достать хотя бы одну цифру из упакованной структуры, платформе необходимо выгрузить весь бинарный блок из базы, передать его на сервер 1С и полностью десериализовать (распаковать) в оперативной памяти.
Рассмотрим стандартный способ работы с такими данными. Обращение к константе происходит в два этапа: сначала мы получаем сам объект ХранилищеЗначения из таблицы констант, а затем вызываем его внутренний метод Получить() для извлечения реальных данных.
Посмотрим на пример кода, который демонстрирует это действие:
// Получаем объект хранилища из константы
ОбъектХранилища = Константы.МоиНастройкиПроекта.Получить();
// Извлекаем реальные данные (например, Структуру)
Если ОбъектХранилища <> Неопределено Тогда
Данные = ОбъектХранилища.Получить();
// Теперь мы можем обратиться к конкретному значению внутри структуры
Если ТипЗнч(Данные) = Тип("Структура") Тогда
НужныйПараметр = Данные.ИмяНужногоПараметра;
КонецЕсли;
КонецЕсли;
Важно помнить, что если в константе ничего не сохранено, метод Константы.ИмяКонстанты.Получить() вернет Неопределено. Попытка вызвать метод .Получить() у Неопределено приведет к ошибке времени выполнения. Поэтому всегда рекомендуем проверять результат на заполненность.
Проанализируем процесс записи. Для того чтобы поместить данные в константу, необходимо сначала создать новый экземпляр объекта ХранилищеЗначения, передав в него наши данные, а затем вызвать метод Установить().
// Подготовим данные для сохранения
Настройки = Новый Структура;
Настройки.Вставить("ДатаОбновления", ТекущаяДата());
Настройки.Вставить("Версия", "1.0.5");
// Упаковываем данные в хранилище и записываем в константу
Константы.МоиНастройкиПроекта.Установить(Новый ХранилищеЗначения(Настройки));
Выясним причину, по которой использование ХранилищеЗначения в константах требует осторожности. В 1С константы кэшируются на стороне сервера и клиента для ускорения доступа. Однако в случае с типом ХранилищеЗначения кэшируется не распакованное значение, а именно сам объект хранилища.
Это приводит к следующим последствиям:
Получить() у хранилища платформа тратит ресурсы на десериализацию и распаковку данных. Если вы делаете это в цикле, производительность системы резко упадет.Разберем нюанс сжатия данных. Конструктор Новый ХранилищеЗначения(Данные, Сжатие) позволяет управлять степенью упаковки. По умолчанию используется стандартное сжатие.
Если вы планируете сохранять данные, которые сами по себе уже сжаты (например, архивы .zip, изображения .png или .jpg), повторное сжатие платформой только увеличит время обработки без существенной экономии места. В таких ситуациях рекомендуется устанавливать уровень сжатия в 0.
Если вам часто требуется обращаться к отдельным значениям из большого набора настроек, использование одной константы с типом ХранилищеЗначения считается плохой практикой разработки. Рассмотрим, чем ее можно заменить:
ХранилищеЗначения, а в измерениях — использовать ключ (например, имя настройки). Таким образом, вы сможете извлекать из базы данных только одну конкретную запись по ключу, не затрагивая остальные настройки.Таким образом, подводя итог: обратиться напрямую к «внутренностям» константы-хранилища невозможно. Нам необходимо всегда извлекать объект целиком, распаковывать его и только потом выбирать нужный элемент. Если такая операция выполняется часто и данных много — это верный сигнал к тому, чтобы пересмотреть архитектуру хранения в пользу регистров сведений.