При проектировании учетных систем на платформе 1С:Предприятие часто возникает задача вывода данных из регистров накопления непосредственно в списки документов. Типичный пример: в журнале документов оплаты нужно видеть сумму начисленных по ним бонусов. В этой ситуации перед разработчиком встает дилемма: использовать ли в оборотном регистре измерение с составным типом (в которое могут входить разные виды документов) или разнести разные типы документов по разным измерениям. Давайте подробно разберем, как спроектировать регистр наиболее оптимально с точки зрения производительности и чистоты кода.
Большинство разработчиков склоняются к использованию составного типа данных для измерения ДокументОплаты. Это выглядит логично с точки зрения метаданных и объектной модели. Однако при соединении таких данных в динамических списках возникают нюансы производительности на уровне СУБД.
Рассмотрим ситуацию: если мы просто выполняем ЛЕВОЕ СОЕДИНЕНИЕ в запросе динамического списка по полю с составным типом, SQL-сервер может генерировать неоптимальный план запроса. Чтобы помочь платформе правильно сформировать SQL-запрос, крайне важно использовать типизацию в запросе. Проанализируем пример кода запроса для динамического списка:
ВЫБРАТЬ
Журнал.Ссылка КАК Ссылка,
Журнал.Дата КАК Дата,
ЕСТЬNULL(Бонусы.БонусыОборот, 0) КАК СуммаБонусов
ИЗ
ЖурналДокументов.ПлатежныеДокументы КАК Журнал
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрНакопления.НачислениеБонусов.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Бонусы
ПО
Журнал.Ссылка = ВЫРАЗИТЬ(Бонусы.ДокументОплаты КАК Документ.ОплатаНаличными)
ИЛИ Журнал.Ссылка = ВЫРАЗИТЬ(Бонусы.ДокументОплаты КАК Документ.ОплатаКартой)
Зачем нужно использовать ВЫРАЗИТЬ? В системе 1С при обращении к составному полю СУБД анализирует несколько колонок (идентификатор типа и GUID ссылки). Оператор ВЫРАЗИТЬ в запросе — это не просто приведение типов, это явное указание платформе, к какой физической таблице нужно обращаться. Это позволяет избежать избыточных соединений (JOIN) со всеми возможными таблицами, входящими в составной тип, что значительно ускоряет выполнение запроса.
Альтернативный подход — создать измерения ДокументОплатыТип1 и ДокументОплатыТип2. С точки зрения «чистоты» архитектуры 1С это считается менее правильным («кощунством»), однако с точки зрения SQL такой подход может быть быстрее, так как индекс по конкретному полю (не составному) всегда компактнее и эффективнее.
Тем не менее, мы рекомендуем избегать этого варианта, если количество типов документов может увеличиться. Это приведет к необходимости переписывать запросы, отчеты и логику проведения при каждом расширении функционала. Разберем, в каких случаях это допустимо: только если вы на 100% уверены, что список типов документов никогда не изменится, и вы боретесь за миллисекунды в высоконагруженной системе.
Проанализируем ситуацию глубже. Если основная цель создания измерения в регистре — это вывод данных в динамический список, то использование регистра как источника данных для списка может быть методической ошибкой. При больших объемах данных соединение с виртуальными таблицами в динамическом списке неизбежно приведет к замедлению интерфейса.
Рекомендуемое решение:
Рассмотрим механизм избыточности. Если пользователям важно видеть сумму бонусов в списке, мы можем добавить реквизит СуммаБонусов непосредственно в документы оплаты. Рассмотрим алгоритм реализации:
СуммаБонусов (число).НачислениеБонусов, программно обновляем этот реквизит в документе.Это обеспечит максимально возможную скорость работы интерфейса, так как данные будут считываться из одной физической таблицы документа.
Если архитектура не позволяет менять структуру документов, рассмотрим современный механизм платформы 8.3.10+ — событие ПриПолученииДанныхНаСервере или механизм обработки данных динамического списка. Это позволяет вычислять или подтягивать значения из регистров порционно, только для тех строк, которые отображаются на экране пользователя в данный момент.
Выясним причину выбора этого метода: он исключает тяжелое соединение в основном запросе списка. Список открывается мгновенно, а дополнительные данные подгружаются отдельным легким запросом по массиву ссылок, видимых на экране.
Важно помнить, что измерение с типом «Документ» в оборотном регистре — это «тяжелое» решение. Выясним почему:
Для каждого документа в таблице итогов регистра создается отдельная запись. В итоге таблица агрегатов (итогов) по размеру становится сопоставима с таблицей самих движений. Это делает использование виртуальной таблицы Обороты неэффективным.
Практический совет: Если вам нужно хранить связь «Документ — Сумма» и вы не планируете анализировать обороты в разрезе периодов (день, месяц), рассмотрите использование Регистра сведений. Он работает быстрее при получении конкретных значений по ключу (документу) и не создает лишней нагрузки на механизм расчета итогов.
Подводя итог, проанализируем последовательность действий при проектировании:
ВЫРАЗИТЬ в запросах.