Как оптимизировать хранение большого количества редко заполняемых реквизитов в справочниках 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

При проектировании крупных учетных систем (например, для ЖКХ, ERP-решений или WMS) разработчики регулярно сталкиваются с дилеммой: как организовать хранение множества дополнительных характеристик объектов, если эти характеристики нужны далеко не для каждого элемента справочника? В этой статье мы подробно разберем ситуацию, когда справочник (например, «Помещения» или «Лицевые счета») содержит более 40 реквизитов, заполняемых избирательно, а количество записей измеряется десятками и сотнями тысяч элементов.

Мы проанализируем различные архитектурные подходы с точки зрения производительности СУБД (MS SQL Server, PostgreSQL), удобства написания запросов и особенностей платформы «1С:Предприятие 8». Также мы выясним причину распространенной проблемы, когда соединение небольших таблиц в запросах начинает занимать критически много времени.

---

Подход 1: Денормализация (все реквизиты хранятся в шапке справочника)

Это самый простой и очевидный подход. Все 40 реквизитов создаются как обычные поля справочника. На первый взгляд, это кажется неоптимальным («база будет раздуваться из-за пустых полей»), однако давайте проанализируем ситуацию на физическом уровне хранения данных в СУБД.

Современные СУБД хранят данные страницами (обычно по 8 КБ). Пустые значения простых типов данных (числа, даты, булево) или пустые ссылки практически не занимают физического места на диске благодаря использованию битовой карты NULL-значений (NULL bitmap). Таким образом, объем базы данных при наличии пустых реквизитов увеличивается незначительно.

Однако здесь кроется другая проблема, специфичная для объектной модели «1С:Предприятие»:

  1. При обращении к объекту в коде через метод ПолучитьОбъект() платформа 1С выполняет SQL-запрос, который считывает из СУБД абсолютно все поля шапки и табличных частей. Если у вас заполнено 3 реквизита из 40, остальные 37 пустых значений все равно будут переданы по сети на сервер приложений 1С и загружены в оперативную память процесса rphost.
  2. Чем шире строка таблицы в СУБД, тем меньше записей помещается на одной физической странице данных. При выполнении запросов СУБД считывает данные из дисковой подсистемы в оперативную память (буферный пул) страницами. Если строки широкие, СУБД придется выполнить больше операций ввода-вывода (I/O) для сканирования таблицы, что снизит скорость чтения списков и групповых выборок.

Рекомендация: Если реквизиты активно используются в расчетах и отборах, а объем справочника не превышает 100 000 элементов, их размещение в шапке справочника будет наиболее быстродействующим вариантом для чтения через запросы, так как СУБД выполнит выборку из одной физической таблицы без соединений.

---

Подход 2: Хранение в табличной части справочника

Иногда разработчики предлагают перенести редко заполняемые реквизиты в табличную часть (ТЧ) справочника, создав там структуру «одна строка со всеми свойствами» или «ключ-значение».

Давайте разберем, почему этот паттерн является крайне нежелательным:

  1. Физически любая табличная часть в 1С — это отдельная таблица в СУБД, связанная с основной таблицей справочника по полю Ссылка. Каждое обращение к свойствам ТЧ в запросе потребует операции ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN).
  2. Согласно стандартам разработки фирмы «1С» (опубликованным на ИТС), использование табличных частей для хранения уникальных свойств объектов не рекомендуется. Контролировать уникальность и наличие ровно одной строки в ТЧ придется программно при записи объекта, что усложняет код и повышает риск возникновения логических ошибок.
  3. СУБД не сможет эффективно построить индексы по полям внутри табличной части для быстрого поиска элементов основного справочника.

---

Подход 3: Модель EAV (План видов характеристик и Регистр сведений)

Этот подход реализован в Библиотеке стандартных подсистем (БСП) в виде механизма «Дополнительные реквизиты и сведения». На физическом уровне это классическая модель EAV (Entity-Attribute-Value):

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

Однако с точки зрения производительности массовых расчетов (например, ежемесячное начисление коммунальных услуг по 30 000 лицевых счетов) модель EAV превращается в проблему. Представим, что для расчета начисления нам нужно получить 6 различных свойств помещения (общая площадь, жилая площадь, количество зарегистрированных, этаж, тип отопления, наличие лифта). Нам придется написать запрос с шестью левыми соединениями к одной и той же таблице регистра сведений:


ВЫБРАТЬ
    Помещения.Ссылка КАК Помещение,
    ЕСТЬNULL(Свойство1.Значение, 0) КАК ОбщаяПлощадь,
    ЕСТЬNULL(Свойство2.Значение, 0) КАК ЖилаяПлощадь,
    ЕСТЬNULL(Свойство3.Значение, 0) КАК КоличествоПрописанных
ИЗ
    Справочник.Помещения КАК Помещения
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК Свойство1
        ПО Свойство1.Объект = Помещения.Ссылка
        И Свойство1.Свойство = &СвойствоОбщаяПлощадь
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК Свойство2
        ПО Свойство2.Объект = Помещения.Ссылка
        И Свойство2.Свойство = &СвойствоЖилаяПлощадь
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК Свойство3
        ПО Свойство3.Объект = Помещения.Ссылка
        И Свойство3.Свойство = &СвойствоКоличествоПрописанных

Для СУБД такой запрос крайне тяжел. Многократные соединения одной и той же таблицы приводят к неверной оценке кардинальности оптимизатором запросов, из-за чего SQL-сервер может выбрать неоптимальный план выполнения (например, сканирование индекса вместо поиска по ключу).

---

Подход 4: Хранение свойств в формате JSON

Интересный и современный подход — сериализация всех редких и вспомогательных свойств в одну текстовую строку неограниченной длины в формате JSON и хранение ее в одном реквизите справочника.

Начиная с версии платформы 8.3.23, работа с JSON в 1С стала очень быстрой благодаря встроенным методам сериализации. Рассмотрим пример записи свойств объекта в JSON:


// Пример упаковки свойств объекта в строку JSON
ПараметрыОбъекта = Новый Структура;
ПараметрыОбъекта.Вставить("КадастровыйНомер", "77:01:0001001:1234");
ПараметрыОбъекта.Вставить("ГисЖкхИдентификатор", "DOM-REG-98765");
ПараметрыОбъекта.Вставить("ДатаВводаВЭксплуатацию", ТекущаяДата());

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьЗначениеJSON(ЗаписьJSON, ПараметрыОбъекта);
СтрокаJSON = ЗаписьJSON.Закрыть();

// СтрокаJSON записывается в реквизит справочника "ДополнительныеПараметры"

При необходимости прочитать эти данные на форме элемента справочника мы выполняем обратную операцию:


// Пример чтения свойств из строки JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Объект.ДополнительныеПараметры);
ПараметрыОбъекта = ПрочитатьЗначениеJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();

КадастровыйНомер = ПараметрыОбъекта.КадастровыйНомер;

Преимущества: Таблица справочника остается максимально узкой. Запись и чтение объекта выполняются мгновенно. Структура свойств гибкая и может меняться без доработки метаданных.

Критический недостаток: Язык запросов 1С не умеет работать с JSON-строками. Вы не сможете написать запрос с отбором по кадастровому номеру или рассчитать сумму начислений по площади, хранящейся внутри JSON. Этот метод подходит исключительно для хранения справочной информации, которая выводится на форму и никогда не участвует в выборках, расчетах и отчетах.

---

Подход 5: Вертикальное секционирование (Регистры сведений)

Давайте найдем «золотую середину». Вертикальное секционирование — это разделение реквизитов на группы по частоте их использования и вынесение редко используемых параметров во внешние таблицы СУБД (в контексте 1С — в непериодические Регистры сведений).

Проанализируем структуру данных типичного ЖКХ-решения. Реквизиты справочника «Помещения» можно разделить на три логические группы:

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

Этот подход гарантирует:

---

Почему соединение 9 таблиц по 2-3 тыс. элементов может занимать 5 секунд?

Разработчик в обсуждении упомянул проблему: на мощном сервере (процессор i9, 64 ГБ оперативной памяти) левое соединение 9 таблиц объемом всего по 2 000 – 3 000 элементов выполняется около 5 секунд. На таких объемах это катастрофически медленно. Давайте выясним причины такого поведения СУБД и способы локализации проблемы:

  1. Соединение по полям составного типа данных. Это самая частая ошибка разработчиков 1С. Если поле связи в одной из таблиц имеет составной тип (например, реквизит может содержать ссылку на Документ.Начисление или Документ.Оплата), платформа 1С на уровне СУБД транслирует это соединение в гигантскую конструкцию со множеством CASE WHEN и LEFT JOIN для всех физических таблиц документов, входящих в составной тип. СУБД не может применить индекс и переходит на полное сканирование таблиц (Table/Index Scan). Правило: соединять таблицы в запросах можно исключительно по полям простых ссылочных типов.
  2. Отсутствие индексов по полям связи. Убедитесь, что для всех реквизитов, по которым происходит левое соединение (включая измерения регистров сведений), в Конфигураторе включено свойство Индексировать (или они являются ведущими измерениями).
  3. Неявные соединения через точку. Конструкции в запросах вида Выборка.Помещение.Владелец.Адрес.Город приводят к созданию платформой неявных левых соединений. Если таких обращений в запросе много, итоговый SQL-текст будет перегружен скрытыми соединениями, что парализует оптимизатор СУБД. Выбирайте данные только через явные соединения в запросе.
  4. Устаревшая статистика СУБД. Если в базе данных происходит частая запись и удаление информации, оптимизатор СУБД может строить неверные планы выполнения из-за неактуальной статистики распределения данных. Убедитесь, что на сервере СУБД настроено ежедневное (или более частое) регламентное задание по обновлению статистики (UPDATE STATISTICS).

---

Резюме: пошаговый план проектирования

Для создания быстрой и масштабируемой системы хранения редко заполняемых реквизитов выполним следующие шаги:

  1. Проведем аудит всех 40 реквизитов. Разделим их по частоте использования в расчетных алгоритмах и отчетах.
  2. Реквизиты первой необходимости (до 10–15 полей), критически важные для ядра системы, оставим в справочнике.
  3. Параметры для интеграции и редких регламентных проверок перенесем в подчиненные регистры сведений с типом связи «один-к-одному» (измерение — ссылка на справочник).
  4. Исключим использование модели EAV (дополнительных реквизитов БСП) в циклических расчетных алгоритмах. Заменим их на жестко типизированные регистры сведений.
  5. Для сугубо справочной текстовой информации, которая нужна только для отображения в карточке объекта, применим хранение в формате JSON в одной строке неограниченной длины.
← На главную