В процессе проектирования сложных информационных систем на платформе 1С:Предприятие 8 разработчики иногда сталкиваются с необходимостью хранения огромного количества параметров в одной записи. Это может быть связано с интеграцией с внешними системами, сложным импортом из плоских таблиц вроде Excel или проектированием гибких аналитических моделей. Первым делом у разработчика возникает вопрос: существуют ли жесткие лимиты на количество измерений, ресурсов и реквизитов в регистрах сведений? И к каким архитектурным последствиям может привести создание «сверхшироких» таблиц?
В этой статье мы подробно проанализируем технические ограничения платформы 1С и СУБД, разберем физическую структуру таблиц «под капотом» и рассмотрим практические пути решения этой задачи.
При использовании клиент-серверного варианта работы база данных физически разворачивается на СУБД (MS SQL Server, PostgreSQL, IBM DB2 или Oracle Database). Платформа 1С транслирует объекты метаданных в физические таблицы СУБД. Соответственно, базовые лимиты базы данных напрямую влияют на возможности 1С. Для оценки реального влияния метаданных на физический размер таблиц СУБД можно использовать инструмент для анализа дискового пространства базы данных.
Рассмотрим ограничения наиболее популярных СУБД:
Если мы попытаемся создать регистр сведений, в котором суммарное количество измерений, ресурсов и реквизитов приближается к 1000, мы гарантированно столкнемся с ошибкой СУБД при попытке реструктуризации базы данных.
Важнейший нюанс, который часто упускают начинающие разработчики: одно поле в конфигураторе 1С далеко не всегда соответствует одной колонке в СУБД. Если ваше поле (ресурс, реквизит или измерение) имеет составной тип данных, платформа 1С вынуждена создавать для него несколько физических колонок для корректной типизации в базе данных.
Проанализируем структуру хранения составного поля в СУБД. Для хранения ссылки составного типа платформа создает следующие служебные колонки:
_TYPE)._RTRef)._RRRef).Таким образом, если у вас в регистре создано всего 250 ресурсов, но каждый из них имеет составной тип данных (например, включает ссылку на несколько справочников и документов), реальное количество колонок в таблице SQL превысит 1000! В результате платформа выдаст критическую ошибку при обновлении конфигурации задолго до того, как вы достигнете номинального лимита в 1024 поля в конфигураторе.
Даже если общее количество колонок укладывается в рамки лимитов, существует еще одно фундаментальное ограничение СУБД — максимальный размер одной физической строки данных. Для MS SQL Server этот лимит составляет 8060 байт.
В этот лимит не входят поля неограниченной длины (длинные строки, файлы и двоичные данные), так как они хранятся на СУБД в отдельных структурах (LOB-данные). Однако все поля фиксированной длины (числа, даты, булево, короткие строки фиксированной длины, уникальные идентификаторы ссылок) хранятся непосредственно в строке таблицы. Если вы создадите сотни полей типов Число или Строка(100), суммарный вес строки превысит 8060 байт, и запись данных станет физически невозможной.
Для регистров сведений критически важна уникальность записей, которая обеспечивается набором его измерений. Для обеспечения быстрого поиска и уникальности платформа 1С автоматически строит индексы по комбинации измерений регистра. Здесь в силу вступают жесткие ограничения СУБД на работу с индексами:
Не забывайте, что часть доступных колонок СУБД платформа резервирует под системные нужды. В зависимости от свойств вашего регистра сведений, СУБД создаст дополнительные служебные поля:
Период — для периодических регистров сведений.Регистратор и НомерСтроки — для регистров, подчиненных регистратору.Активность — признак активности записи для подчиненных регистров.Эти поля забирают у разработчика еще порядка 10–12 доступных колонок СУБД.
Даже если вам удастся уместить 500 реквизитов в рамки ограничений СУБД, вы неизбежно столкнетесь с серьезными проблемами производительности:
СрезПоследних и СрезПервых будут выполняться критически медленно. СУБД будет тратить огромное количество времени и ресурсов процессора на сканирование тяжелых индексов и выполнение соединений.Что делать, если бизнес-логика все же требует хранения сотен или тысяч параметров? Рассмотрим три проверенных архитектурных решения.
Вместо создания 1000 колонок (ресурсов) мы можем спроектировать регистр сведений по классической схеме Entity-Attribute-Value (Сущность-Атрибут-Значение). Сделаем структуру регистра следующей:
В такой структуре количество параметров для одного объекта может быть бесконечным, при этом таблица регистра в СУБД будет оставаться узкой, состоящей всего из нескольких колонок.
Если параметры нужны вам преимущественно для отображения на форме или для обработки в коде в виде единого объекта, а поиск и фильтрация в запросах по конкретным параметрам не планируются, отличным решением будет упаковка данных в один ресурс с типом ХранилищеЗначения. При необходимости можно использовать методы сжатия строковых данных средствами 1С.
Рассмотрим пример кода, как можно свернуть произвольную структуру параметров и записать ее в регистр сведений:
// Подготовим структуру с параметрами
ПараметрыДляЗаписи = Новый Структура;
ПараметрыДляЗаписи.Вставить("Параметр1", "Значение1");
ПараметрыДляЗаписи.Вставить("Параметр2", 12345);
ПараметрыДляЗаписи.Вставить("Параметр1000", Истина);
// Упакуем структуру в Хранилище Значения
ХранилищеПараметров = Новый ХранилищеЗначения(ПараметрыДляЗаписи, Новый СжатиеДанных(9));
// Запишем данные в регистр сведений
МенеджерЗаписи = РегистрыСведений.ПараметрыОбъектов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СсылкаНаОбъект;
МенеджерЗаписи.ДанныеПараметров = ХранилищеПараметров;
МенеджерЗаписи.Записать();
А теперь проанализируем, как прочитать эти параметры обратно для работы:
// Прочитаем запись регистра
МенеджерЗаписи = РегистрыСведений.ПараметрыОбъектов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СсылкаНаОбъект;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
// Извлечем структуру из хранилища
ПараметрыОбъекта = МенеджерЗаписи.ДанныеПараметров.Получить();
Если ТипЗнч(ПараметрыОбъекта) = Тип("Структура") Тогда
ЗначениеПараметра1 = ПараметрыОбъекта.Параметр1;
// Продолжаем обработку параметров
КонецЕсли;
КонецЕсли;
Важно: Помните, что данный подход полностью исключает возможность эффективной фильтрации или сортировки по внутренним свойствам структуры внутри запросов 1С. Этот метод подходит исключительно для задач отображения и постобработки данных на клиенте или сервере приложений.
Если ваша система оперирует огромным массивом слабоструктурированных данных (например, карточки товаров интернет-магазина с уникальным набором характеристик для каждой категории), целесообразно вынести хранение таких параметров во внешнюю NoSQL базу данных (например, MongoDB, Redis). В платформе 1С в таком случае будет храниться только ссылка на идентификатор документа во внешней базе данных, а интеграция будет осуществляться через HTTP-сервисы или REST API.
При проектировании регистров сведений в 1С всегда придерживайтесь правила: «Таблицы должны расти в высоту (количеством строк), а не в ширину (количеством колонок)». Оптимальное количество ресурсов и реквизитов для одной таблицы регистра — в пределах нескольких десятков. Если архитектура требует большего, используйте модель EAV или упаковку данных в ХранилищеЗначения.