При проектировании документов в 1С перед разработчиком часто возникает задача связывания создаваемого документа с документом-основанием. Например, документ Накладная может создаваться как на основании документа Заявка, так и на основании другой Накладной (в случае оформлении возврата). Возникает архитектурная дилемма: создать один реквизит ДокументОснование составного типа (ДокументСсылка.Заявка, ДокументСсылка.Накладная) или же завести два отдельных реквизита однозначного ссылочного типа — Заявка и НакладнаяКВозврату?
Рассмотрим подробно оба подхода, разберем их технические особенности, влияние на производительность СУБД, масштабируемость системы и удобство написания запросов.
Проанализируем два основных варианта реализации связи с основанием:
ДокументОснование может хранить ссылку на один из нескольких типов документов. Этот вариант традиционно используется во многих типовых конфигурациях 1С.Заявка и НакладнаяКВозврату, каждый из которых имеет строго один ссылочный тип.Разберем основные причины, почему разработчики и авторы типовых решений 1С отдают предпочтение составным типам:
1. Высокая масштабируемость и гибкость архитектуры
Бизнес-процессы предприятия со временем меняются. Если заказчик попросит вводить документ на основании нового объекта (например, РеализацияТоваровУслуг или ЗаказПокупателя), в случае составного типа достаточно просто расширить состав типов в существующем реквизите. При использовании раздельных реквизитов придется добавлять новые реквизиты в объект, выносить их на формы и корректировать логику проведения.
2. Лаконичность и простота запросов
При обращении к реквизитам документа-основания через точку в простом коде или запросе платформе требуется задействовать только одно поле. Например, получение номера основания в первом варианте выглядит лаконично:
ВЫБРАТЬ
Накладная.ДокументОснование.Номер КАК НомерОснования
ИЗ
Документ.Накладная КАК Накладная
Если же используются два разных поля, разработчику приходится вручную объединять данные или использовать функции проверки на пустую ссылку:
ВЫБРАТЬ
ЕСТЬNULL(Заявка.Номер, НакладнаяКВозврату.Номер) КАК НомерОснования
ИЗ
Документ.Накладная КАК Накладная
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Заявка КАК Заявка
ПО Накладная.Заявка = Заявка.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Накладная КАК НакладнаяКВозврату
ПО Накладная.НакладнаяКВозврату = НакладнаяКВозврату.Ссылка
3. Единое отображение в структуре подчиненности
Для отображения иерархии документов используется механизм критериев отбора. При использовании единого составного реквизита достаточно указать одно поле в составе критерия отбора. Впрочем, при раздельных реквизитах оба поля также можно добавить в один критерий отбора, поэтому данный фактор не является ограничением.
Несмотря на удобство составных типов, необходимо учитывать специфику их хранения и обработки на уровне системы управления базами данных (СУБД):
1. Хранение данных в базе
Реквизит однозначного ссылочного типа занимает в таблице СУБД ровно одну колонку (уникальный идентификатор UUID). Реквизит составного типа хранится сразу в трех колонках:
_TYPE);_RTRef);_RRRef).Это приводит к некоторому увеличению объемов таблицы и индексов СУБД.
2. Оптимизация запросов и синтаксис ВЫРАЗИТЬ
При обращении к реквизитам составного поля через точку платформа 1С автоматически генерирует в SQL-запросе неявные левые соединения (LEFT JOIN) ко всем таблицам документов, входящим в состав типа. Если состав типов слишком широк, запрос может существенно замедлиться.
Для предотвращения проблем с производительностью стандарты разработки 1С требуют явно ограничивать тип с помощью конструкции ВЫРАЗИТЬ(...):
ВЫБРАТЬ
ВЫРАЗИТЬ(Накладная.ДокументОснование КАК Документ.Заявка).Номер КАК НомерЗаявки
ИЗ
Документ.Накладная КАК Накладная
3. Особенности интерфейса
При интерактивном выборе значения в поле составного типа пользователь на управляемой форме сначала сталкивается с диалоговым окном выбора типа метаданных, что добавляет лишнее действие (клик мышью). Для однозначных ссылочных полей форма выбора документа открывается сразу.
4. Взаимодействие с внешними системами и функциональными опциями
Разделение полей дает преимущества при интеграции через REST API (OData) или сервисы XML/JSON, так как схема данных остается строго определенной. Кроме того, раздельные реквизиты легко привязываются к функциональным опциям платформы, скрывающим неиспользуемые поля интерфейса автоматически.
Подведем итоги и проанализируем, когда следует выбирать тот или иной вариант:
Выбирайте составной тип, если:
Выбирайте раздельные реквизиты, если:
Заявка, и НакладнаяКВозврату.