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

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

При проектировании учетных систем на платформе 1С:Предприятие часто возникает задача вывода данных из регистров накопления непосредственно в списки документов. Типичный пример: в журнале документов оплаты нужно видеть сумму начисленных по ним бонусов. В этой ситуации перед разработчиком встает дилемма: использовать ли в оборотном регистре измерение с составным типом (в которое могут входить разные виды документов) или разнести разные типы документов по разным измерениям. Давайте подробно разберем, как спроектировать регистр наиболее оптимально с точки зрения производительности и чистоты кода.

Вариант 1: Использование составного типа данных и оператора ВЫРАЗИТЬ

Большинство разработчиков склоняются к использованию составного типа данных для измерения ДокументОплаты. Это выглядит логично с точки зрения метаданных и объектной модели. Однако при соединении таких данных в динамических списках возникают нюансы производительности на уровне СУБД.

Рассмотрим ситуацию: если мы просто выполняем ЛЕВОЕ СОЕДИНЕНИЕ в запросе динамического списка по полю с составным типом, SQL-сервер может генерировать неоптимальный план запроса. Чтобы помочь платформе правильно сформировать SQL-запрос, крайне важно использовать типизацию в запросе. Проанализируем пример кода запроса для динамического списка:


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

Зачем нужно использовать ВЫРАЗИТЬ? В системе 1С при обращении к составному полю СУБД анализирует несколько колонок (идентификатор типа и GUID ссылки). Оператор ВЫРАЗИТЬ в запросе — это не просто приведение типов, это явное указание платформе, к какой физической таблице нужно обращаться. Это позволяет избежать избыточных соединений (JOIN) со всеми возможными таблицами, входящими в составной тип, что значительно ускоряет выполнение запроса.

Вариант 2: Использование нескольких измерений под каждый тип

Альтернативный подход — создать измерения ДокументОплатыТип1 и ДокументОплатыТип2. С точки зрения «чистоты» архитектуры 1С это считается менее правильным («кощунством»), однако с точки зрения SQL такой подход может быть быстрее, так как индекс по конкретному полю (не составному) всегда компактнее и эффективнее.

Тем не менее, мы рекомендуем избегать этого варианта, если количество типов документов может увеличиться. Это приведет к необходимости переписывать запросы, отчеты и логику проведения при каждом расширении функционала. Разберем, в каких случаях это допустимо: только если вы на 100% уверены, что список типов документов никогда не изменится, и вы боретесь за миллисекунды в высоконагруженной системе.

Вариант 3: Денормализация данных (Хранение суммы в документе)

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

Рекомендуемое решение: Рассмотрим механизм избыточности. Если пользователям важно видеть сумму бонусов в списке, мы можем добавить реквизит СуммаБонусов непосредственно в документы оплаты. Рассмотрим алгоритм реализации:

  1. Добавляем в документы оплаты (Тип 1 и Тип 2) обычный реквизит СуммаБонусов (число).
  2. При проведении документа или при записи движений в регистр НачислениеБонусов, программно обновляем этот реквизит в документе.
  3. В динамическом списке мы просто выводим поле документа без всяких соединений с регистром.

Это обеспечит максимально возможную скорость работы интерфейса, так как данные будут считываться из одной физической таблицы документа.

Вариант 4: Использование механизма «Обработка и оформление данных»

Если архитектура не позволяет менять структуру документов, рассмотрим современный механизм платформы 8.3.10+ — событие ПриПолученииДанныхНаСервере или механизм обработки данных динамического списка. Это позволяет вычислять или подтягивать значения из регистров порционно, только для тех строк, которые отображаются на экране пользователя в данный момент.

Выясним причину выбора этого метода: он исключает тяжелое соединение в основном запросе списка. Список открывается мгновенно, а дополнительные данные подгружаются отдельным легким запросом по массиву ссылок, видимых на экране.

Проблема измерения с типом «Документ» в оборотном регистре

Важно помнить, что измерение с типом «Документ» в оборотном регистре — это «тяжелое» решение. Выясним почему: Для каждого документа в таблице итогов регистра создается отдельная запись. В итоге таблица агрегатов (итогов) по размеру становится сопоставима с таблицей самих движений. Это делает использование виртуальной таблицы Обороты неэффективным.

Практический совет: Если вам нужно хранить связь «Документ — Сумма» и вы не планируете анализировать обороты в разрезе периодов (день, месяц), рассмотрите использование Регистра сведений. Он работает быстрее при получении конкретных значений по ключу (документу) и не создает лишней нагрузки на механизм расчета итогов.

Итоги и рекомендации

Подводя итог, проанализируем последовательность действий при проектировании:

  1. Если данных немного и важна быстрота разработки — оставляйте составной тип, но обязательно используйте ВЫРАЗИТЬ в запросах.
  2. Если планируется высокая нагрузка и огромные журналы документов — используйте денормализацию (храните сумму в реквизите документа).
  3. Проверьте, индексировано ли измерение. Помните, что стандартный индекс начинается с периода, поэтому для быстрого поиска по документу без фильтра по дате может потребоваться дополнительный индекс.
  4. Всегда оценивайте, нужен ли вам именно Регистр накопления. Часто для связи объектов и их стоимостных характеристик лучше подходит Регистр сведений.
← На главную