При разработке сложных интерфейсов на платформе 1С программисты часто сталкиваются с необходимостью вывода огромного количества полей в одной форме списка. Если данные собираются из нескольких источников (документы, бизнес-процессы, регистры) с помощью пакетных запросов или сложных соединений, производительность динамического списка может резко упасть, особенно при наложении пользовательских отборов. Разберем подробно, как работает этот механизм и как правильно оптимизировать такие запросы.
Проанализируем базовый принцип: динамический список не является простым запросом. Это объект, работающий под управлением Системы компоновки данных (СКД). По умолчанию, когда пользователь устанавливает отбор в форме, платформа пытается «умным» способом внедрить это условие в текст SQL-запроса. Однако в случае с пакетными запросами и временными таблицами этот процесс усложняется.
Если в тексте запроса не указаны специальные инструкции, платформа оборачивает ваш итоговый запрос во внешний запрос. Схематично это выглядит так:
SELECT * FROM (
// Ваш сложный пакетный запрос
ВЫБРАТЬ ... ИЗ ...
) КАК СводнаяТаблица
ГДЕ СводнаяТаблица.Организация = &ПараметрОтбора
Проблема такого подхода заключается в том, что СУБД сначала может попытаться выполнить весь ваш вложенный запрос (включая все соединения и расчеты во временных таблицах), и только потом отсечь лишние строки. Это нивелирует пользу индексов и приводит к избыточному чтению данных. Выясним причину тормозов: чаще всего они связаны с тем, что отбор не «пробрасывается» внутрь подзапросов или временных таблиц автоматически.
Чтобы отбор накладывался эффективно, необходимо явно указать платформе, в какие части запроса следует подставлять пользовательские фильтры. Для этого используются фигурные скобки — инструкции построителя или СКД {ГДЕ ...}. Рассмотрим подробнее, как это реализовать.
Если у вас есть выборка из основной таблицы и несколько соединений, пропишите условие в тех местах, где данные должны фильтроваться на раннем этапе:
ВЫБРАТЬ
Заявки.Ссылка,
Заявки.Организация,
Оплаты.СуммаОплаты
ИЗ
Документ.ЗаявкаНаРасходованиеДенежныхСредств КАК Заявки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Оплаты КАК Оплаты
ПО Заявки.Ссылка = Оплаты.ДокументОснования
{ГДЕ
Заявки.Организация.*,
Заявки.Дата}
При таком подходе, если пользователь установит отбор по организации, платформа вставит условие непосредственно в секцию ГДЕ основного запроса к таблице документов, что позволит СУБД использовать индекс по полю Организация.
В динамических списках использование временных таблиц (пакетных запросов) часто считается «плохой практикой» именно из-за сложности оптимизации отборов. Платформа не пробрасывает условия внутрь временных таблиц, если это не указано явно. Если вы все же используете пакетный запрос, проанализируем ситуацию: отборы нужно расставить в каждом запросе пакета, где это критично для объема данных.
Важный нюанс: если в динамическом списке не указана «Основная таблица», платформа теряет возможность выполнять оптимизированные выборки порциями. В сочетании с пакетным запросом это гарантированно приведет к полному сканированию таблиц (Full Scan) на уровне SQL-сервера.
Часто разработчики замечают, что под полными правами список «летает», а под ограниченными — «тормозит». Разберем, почему так происходит. При использовании RLS платформа добавляет свои условия проверки прав к каждой таблице в запросе. Если запрос пакетный и сложный, итоговый текст SQL-запроса разрастается экспоненциально. Количество соединений может превысить разумные пределы, что приводит к критическому падению производительности.
Если количество соединений в динамическом списке зашкаливает (как в примере автора: бизнес-процессы, оплаты, файлы, доп. реквизиты), лучшим решением будет отказ от динамического формирования этой «простыни» данных. Посмотрим на архитектурно правильный путь:
СводныеДанныеЗаявок).Это нарушает третью нормальную форму базы данных, но в 1С это стандартный и эффективный способ оптимизации тяжелых списков. Отборы по такому регистру будут летать, так как данные уже подготовлены и лежат в одной таблице.
Рассмотрим еще несколько методов, которые помогут ускорить работу формы:
ЛЕВОЕ СОЕДИНЕНИЕ. Используйте вкладку «Характеристики» в конструкторе запроса СКД. Это позволит платформе динамически подключать таблицы доп. сведений только тогда, когда пользователь вывел эту колонку в список или установил по ней отбор.ВЫРАЗИТЬ() для полей составного типа. Это помогает оптимизатору СУБД строить более точные планы запросов при наложении фильтров.Таким образом, для эффективной работы динамического списка с пакетным запросом необходимо либо жестко контролировать места наложения отборов через {ГДЕ}, либо переходить к схеме с агрегирующим регистром сведений.