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

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

При разработке сложных интерфейсов на платформе 1С программисты часто сталкиваются с необходимостью вывода огромного количества полей в одной форме списка. Если данные собираются из нескольких источников (документы, бизнес-процессы, регистры) с помощью пакетных запросов или сложных соединений, производительность динамического списка может резко упасть, особенно при наложении пользовательских отборов. Разберем подробно, как работает этот механизм и как правильно оптимизировать такие запросы.

Механизм работы отборов в динамическом списке

Проанализируем базовый принцип: динамический список не является простым запросом. Это объект, работающий под управлением Системы компоновки данных (СКД). По умолчанию, когда пользователь устанавливает отбор в форме, платформа пытается «умным» способом внедрить это условие в текст SQL-запроса. Однако в случае с пакетными запросами и временными таблицами этот процесс усложняется.

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


SELECT * FROM (
    // Ваш сложный пакетный запрос
    ВЫБРАТЬ ... ИЗ ...
) КАК СводнаяТаблица
ГДЕ СводнаяТаблица.Организация = &ПараметрОтбора

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

Использование инструкций расширения языка запросов {ГДЕ}

Чтобы отбор накладывался эффективно, необходимо явно указать платформе, в какие части запроса следует подставлять пользовательские фильтры. Для этого используются фигурные скобки — инструкции построителя или СКД {ГДЕ ...}. Рассмотрим подробнее, как это реализовать.

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


ВЫБРАТЬ
    Заявки.Ссылка,
    Заявки.Организация,
    Оплаты.СуммаОплаты
ИЗ
    Документ.ЗаявкаНаРасходованиеДенежныхСредств КАК Заявки
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Оплаты КАК Оплаты
    ПО Заявки.Ссылка = Оплаты.ДокументОснования
{ГДЕ
    Заявки.Организация.*,
    Заявки.Дата}

При таком подходе, если пользователь установит отбор по организации, платформа вставит условие непосредственно в секцию ГДЕ основного запроса к таблице документов, что позволит СУБД использовать индекс по полю Организация.

Особенности пакетных запросов и временных таблиц

В динамических списках использование временных таблиц (пакетных запросов) часто считается «плохой практикой» именно из-за сложности оптимизации отборов. Платформа не пробрасывает условия внутрь временных таблиц, если это не указано явно. Если вы все же используете пакетный запрос, проанализируем ситуацию: отборы нужно расставить в каждом запросе пакета, где это критично для объема данных.

Важный нюанс: если в динамическом списке не указана «Основная таблица», платформа теряет возможность выполнять оптимизированные выборки порциями. В сочетании с пакетным запросом это гарантированно приведет к полному сканированию таблиц (Full Scan) на уровне SQL-сервера.

Влияние RLS (ограничения прав доступа)

Часто разработчики замечают, что под полными правами список «летает», а под ограниченными — «тормозит». Разберем, почему так происходит. При использовании RLS платформа добавляет свои условия проверки прав к каждой таблице в запросе. Если запрос пакетный и сложный, итоговый текст SQL-запроса разрастается экспоненциально. Количество соединений может превысить разумные пределы, что приводит к критическому падению производительности.

Альтернативное решение: Сводный регистр сведений

Если количество соединений в динамическом списке зашкаливает (как в примере автора: бизнес-процессы, оплаты, файлы, доп. реквизиты), лучшим решением будет отказ от динамического формирования этой «простыни» данных. Посмотрим на архитектурно правильный путь:

  1. Создаем специальный Регистр сведений (например, СводныеДанныеЗаявок).
  2. В этом регистре создаем измерения для ключевых объектов и ресурсы/реквизиты для всех тех 100500 полей, которые хотят видеть пользователи.
  3. Настраиваем запись в этот регистр при проведении документов или завершении задач бизнес-процессов.
  4. В качестве источника данных для динамического списка выбираем этот один регистр.

Это нарушает третью нормальную форму базы данных, но в 1С это стандартный и эффективный способ оптимизации тяжелых списков. Отборы по такому регистру будут летать, так как данные уже подготовлены и лежат в одной таблице.

Дополнительные советы по оптимизации

Рассмотрим еще несколько методов, которые помогут ускорить работу формы:

Таким образом, для эффективной работы динамического списка с пакетным запросом необходимо либо жестко контролировать места наложения отборов через {ГДЕ}, либо переходить к схеме с агрегирующим регистром сведений.

← На главную