Куда 1С на самом деле записывает содержимое реквизита типа ХранилищеЗначения

· 9 мин

Содержание

Хранилище значений в 1С не создаёт отдельных файлов и каталогов. Содержимое реквизита типа ХранилищеЗначения хранится прямо в базе: в файловом варианте — внутри файла 1Cv8.1CD, в клиент-серверном — в двоичном поле таблицы объекта в СУБД (varbinary(max) в MS SQL Server, bytea в PostgreSQL). Значение сериализуется платформой во внутренний формат и при желании сжимается.

Отсюда простое следствие: найти «папку хранилища» на диске нельзя, зато можно найти таблицу и поле, где лежат данные, оценить их объём и решить, что с ним делать. Ниже — как это сделать в обоих вариантах работы, как настроить сжатие и чем такие реквизиты опасны для скорости и безопасности.

Как устроено хранилище значений и что в него можно положить

ХранилищеЗначения — тип платформы 1С:Предприятие 8.3. Он упаковывает любое сериализуемое значение в один блок двоичных данных и позволяет записать этот блок в реквизит справочника, документа, регистра сведений или табличной части.

Что обычно кладут внутрь:

  • 🖼 картинки и сканы: фото товара, подпись, печать;
  • 📄 файлы целиком в виде ДвоичныеДанные;
  • 📊 таблицы значений, структуры, массивы — например, сохранённые настройки обработки;
  • 🧾 служебные данные: снимки состояния, протоколы обмена, XML-ответы сервисов.

Платформа не «понимает» содержимое хранилища. Для неё это непрозрачный кусок байтов. Поэтому:

  • по такому полю нельзя отбирать, сортировать и группировать в запросе;
  • реквизит нельзя проиндексировать;
  • ссылки, спрятанные внутри хранилища, не участвуют в контроле ссылочной целостности. Удаление помеченных объектов их не увидит, и после удаления в хранилище останется «битая» ссылка.

Не храните внутри ХранилищаЗначения ссылки, которые должны защищать объект от удаления. Для этого нужен обычный реквизит ссылочного типа.

Чем хранилище значений не является

Под похожими названиями в 1С живут ещё четыре механизма. Их часто путают:

МеханизмГде лежат данныеДля чего
Реквизит типа ХранилищеЗначенияТаблица объекта в базеПроизвольные данные объекта
Временное хранилище (ПоместитьВоВременноеХранилище)Память сервера, привязка к сеансу или формеПередача данных между клиентом и сервером
Хранилища настроек (ХранилищеОбщихНастроек и др.)Служебные таблицы настроек в базеПользовательские настройки форм и отчётов
Безопасное хранилище БСПОтдельный регистр сведений с привилегированным доступомПароли, токены, ключи
Хранилище конфигурацииОтдельный файл 1cv8ddb.1CDГрупповая разработка

Дальше речь только о первой строке — о реквизите.

Файловая база: данные внутри 1Cv8.1CD

В файловом варианте вся информационная база — один файл 1Cv8.1CD в каталоге базы. Таблицы, индексы и содержимое хранилищ значений находятся внутри него. Отдельного файла под картинку или документ платформа не создаёт.

Как найти каталог базы:

  1. Откройте окно запуска 1С.
  2. Выделите базу в списке. Внизу окна появится строка подключения вида File="D:\Base\Buh".
  3. Перейдите в этот каталог в проводнике. Там лежит 1Cv8.1CD.

Рядом могут быть и другие файлы, например 1Cv8.cfl — кэш, а также служебные каталоги. Данные реквизитов в них не попадают.

Что это значит на практике:

  • 📈 каждый сохранённый скан на 2 МБ увеличивает 1Cv8.1CD примерно на эту же величину (минус то, что дало сжатие);
  • 🗑 после удаления объектов файл сам не уменьшается — место освобождается внутри, но размер на диске остаётся;
  • 🔧 вернуть место помогает сжатие таблиц информационной базы в режиме «Тестирование и исправление» Конфигуратора или выгрузка-загрузка .dt.

«Тестирование и исправление» и загрузка .dt требуют монопольного доступа: всех пользователей придётся вывести из базы. Перед этим сделайте резервную копию каталога базы.

Если база разрослась до нескольких гигабайт из-за вложений, пора подумать о переводе на клиент-серверный вариант или о хранении файлов вне базы (об этом ниже).

Клиент-серверная база: таблицы и поля в СУБД

В клиент-серверном варианте каждый объект метаданных — это таблица СУБД, а реквизит — поле. Имена служебные: _Reference45 для справочника, _Document112 для документа, _InfoRg1234 для регистра сведений. Реквизит получает имя вида _Fld567.

Тип поля для хранилища значений:

СУБДТип поля
MS SQL Servervarbinary(max) (в старых базах встречается image)
PostgreSQLbytea

Как узнать, в какой таблице лежит реквизит

Имена таблиц и полей не совпадают с названиями в конфигураторе. Соответствие выдаёт функция платформы ПолучитьСтруктуруХраненияБазыДанных(). Её удобно вызвать из внешней обработки на сервере:

&НаСервере
Процедура ПоказатьХранениеНаСервере()
	Объекты = Новый Массив;
	Объекты.Добавить("Справочник.Номенклатура");
	Структура = ПолучитьСтруктуруХраненияБазыДанных(Объекты, Истина);
	Для Каждого СтрокаТаблицы Из Структура Цикл
		Сообщить("Таблица: " + СтрокаТаблицы.ИмяТаблицыХранения);
		Для Каждого Поле Из СтрокаТаблицы.Поля Цикл
			Сообщить("  " + Поле.ИмяПоля + " -> " + Поле.ИмяПоляХранения);
		КонецЦикла;
	КонецЦикла;
КонецПроцедуры

Второй параметр Истина возвращает имена в терминах СУБД. Найдите в выводе имя реквизита и его поле хранения.

Где посмотреть сервер и имя базы данных

Строку подключения в окне запуска вида Srvr="srv1c";Ref="buh" дополняет консоль администрирования серверов 1С:Предприятия. Откройте кластер → «Информационные базы» → свойства базы. Там указаны тип СУБД, сервер баз данных и имя базы в СУБД. Именно в этой базе и лежат таблицы с полями хранилищ.

Оценить, сколько места занимают двоичные данные, можно средствами СУБД:

-- MS SQL Server: размер конкретной таблицы
EXEC sp_spaceused '_Reference45';
-- PostgreSQL: полный размер таблицы вместе с TOAST
SELECT pg_size_pretty(pg_total_relation_size('_reference45'));

💡 В PostgreSQL большие значения bytea уходят в отдельную TOAST-таблицу. Поэтому pg_relation_size покажет маленькую цифру, а реальный объём виден только через pg_total_relation_size.

Чтение таблиц напрямую через СУБД — только для диагностики. Записывать или удалять данные в таблицах 1С средствами SQL нельзя: это нарушает лицензионное соглашение и легко ломает базу.

Как настроить реквизит и сжатие данных

Отдельной «консоли» для хранилищ значений нет. Всё, что настраивается, делается в конфигураторе и в коде.

Создание реквизита

  1. В конфигураторе откройте объект метаданных, например справочник.
  2. Добавьте реквизит и в поле типа выберите ХранилищеЗначения.
  3. Сохраните и обновите конфигурацию базы данных.

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

Запись, чтение и степень сжатия

Сжатие задаётся при создании значения, а не в свойствах реквизита:

// Запись: максимальная степень сжатия (0-9)
ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
Объект.Скан = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
Объект.Записать();

// Чтение
Данные = Объект.Скан.Получить();
Если Данные = Неопределено Тогда
	Сообщить("Реквизит пуст");
КонецЕсли;

Если второй параметр не передать, данные сохраняются без сжатия.

Когда сжатие помогает, а когда нет:

Что хранимЭффект сжатия
XML, JSON, текст, таблицы значенийЗаметный, объём падает в разы
BMP, несжатые TIFFХороший
JPEG, PNG, PDF со сканами, ZIPПочти нулевой: данные уже сжаты

Для уже сжатых форматов уровень 9 только тратит процессор сервера при записи.

Управляемые формы

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

Почему база тормозит из-за хранилищ и как это исправить

Сами по себе хранилища не медленные. Проблемы появляются, когда в них лежат мегабайты, а читают их чаще, чем нужно.

Типичные причины замедления:

  • 🐢 Чтение объекта целиком. Ссылка.ПолучитьОбъект() и обращение к реквизитам через точку от ссылки тянут данные объекта, а с ними и тяжёлое поле. Список из 500 номенклатур с фото по 1 МБ — это полгигабайта по сети.
  • 🐢 Хранилище в динамическом списке или отчёте. Поле попадает в выборку, хотя пользователю не показывается.
  • 🐢 Обмены. Планы обмена выгружают объект целиком. Изменили наименование — улетел и скан.
  • 🐢 Рост резервных копий. .dt и бэкапы СУБД пухнут, восстановление идёт дольше.

Что делать:

  1. Вынести тяжёлые данные из объекта. Создайте регистр сведений с измерением-ссылкой на владельца и ресурсом ХранилищеЗначения. Объект остаётся лёгким, а данные читаются только по запросу. Так устроено хранение двоичных данных файлов в БСП.
  2. Читать запросом только нужные поля. Вместо ПолучитьОбъект() выберите запросом именно те реквизиты, которые нужны, без поля хранилища.
  3. Включать сжатие для текстовых данных и не тратить его на JPEG и PDF.
  4. Хранить файлы в томах на диске. В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) вложения можно хранить не в базе, а в томах — каталогах на сервере. Настройка находится в разделе Администрирование, в блоке работы с файлами; быстрее всего найти её поиском по слову «том». После включения в базе остаются только сведения о файлах.

Как перенести уже накопленные данные

Если тяжёлый реквизит уже заполнен в тысячах объектов, переносите данные порциями:

  1. Создайте регистр сведений с измерением «Владелец» и ресурсом типа ХранилищеЗначения.
  2. Напишите обработку, которая выбирает запросом по 500-1000 ссылок, для каждой копирует значение в регистр и очищает старый реквизит, присваивая ему Новый ХранилищеЗначения(Неопределено).
  3. Каждую порцию записывайте в отдельной транзакции, чтобы не держать блокировки долго.
  4. Перепишите код и формы на чтение из регистра, проверьте на копии базы и только потом запускайте перенос в рабочей.

После переноса место в файловой базе освободится только после сжатия таблиц, а в СУБД — после её штатного обслуживания.

Где хранить двоичные данные объекта?

Кто может прочитать содержимое хранилища

Хранилище значений не шифрует данные. Сжатие — это не защита: распаковать его можно стандартными средствами. Доступ к содержимому определяется только правами на объект.

Кто увидит данные:

  • 👤 любой пользователь, у которого есть право чтения объекта, если в конфигурации есть код или форма, выводящие хранилище;
  • 🛠 администратор с доступом к Конфигуратору или внешним обработкам;
  • 🗄 администратор СУБД: поле читается напрямую, а внутренний формат 1С можно распознать;
  • 💾 любой, у кого оказался файл 1Cv8.1CD, .dt или бэкап СУБД.

Как защититься:

  1. Секреты — в безопасное хранилище. В БСП для паролей и токенов есть процедуры ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище() и функция ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(). Данные лежат в регистре, к которому у пользователей нет прав, и читаются только в привилегированном режиме.
  2. Ограничить права на объект. Если в хранилище персональные данные (сканы паспортов, справки), закройте объект ролями и ограничением доступа на уровне записей.
  3. Защитить копии. Каталог файловой базы и бэкапы — только для учётной записи службы и администраторов. Бэкапы за пределами сервера шифруйте средствами архиватора или СУБД.
  4. Не давать прямой доступ к СУБД пользователям 1С. Учётная запись, под которой сервер 1С подключается к СУБД, не должна использоваться людьми.

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

Частые вопросы

Можно ли посмотреть содержимое хранилища значений без программирования?
Только если в форме объекта есть поле, которое его выводит. Иначе нужна обработка, вызывающая Получить() на сервере.
Есть ли ограничение на размер одного хранилища значений?
Жёсткий предел зависит от СУБД и памяти сервера. На практике значения больше 50-100 МБ лучше не хранить в базе: запись и чтение идут целиком через память рабочего процесса.
Переносится ли содержимое хранилища при выгрузке в .dt?
Да. Выгрузка информационной базы включает все данные таблиц, поэтому хранилища попадают в .dt и увеличивают его размер.
Можно ли сравнить два хранилища значений в запросе?
Нет. Сравнение, отбор и сортировка по полю этого типа в запросе недоступны. Если нужен признак заполненности, заведите отдельный булевый реквизит и ставьте его при записи.
Почему после очистки реквизита файл базы не уменьшился?
Файловая база не отдаёт место на диск сама. Сожмите таблицы в «Тестировании и исправлении» или выполните выгрузку и загрузку .dt.