При работе с Системой компоновки данных (СКД) часто возникает вопрос: когда именно применяются отборы, заданные пользователем или программно? Понимание этого механизма критически важно для оптимизации производительности отчетов и правильной интерпретации результатов, особенно при работе со сложными иерархическими данными. Давайте разберемся, применяются ли отборы в момент формирования текста запроса к базе данных или уже после получения всей выборки на этапе постобработки.
Система компоновки данных — это мощный инструмент, который не просто выполняет ваш запрос, но и старается его оптимизировать. Главный принцип этой оптимизации — перенести как можно больше вычислений и фильтрации на сторону СУБД. Это означает, что СКД всегда будет стремиться включить условия отбора непосредственно в текст запроса, добавляя их в секцию ГДЕ (WHERE).
Почему это важно? Если отбор применяется на уровне запроса, то база данных сразу возвращает только нужные записи. Это значительно сокращает объем передаваемых данных и ускоряет формирование отчета. Если же отбор применяется после, то сначала из базы извлекается большой, избыточный набор данных, и только потом платформа 1С фильтрует его. Это медленнее и требует больше оперативной памяти.
Таким образом, момент применения отбора не является случайным или непредсказуемым. Он зависит от того, сможет ли СКД "понять" условие отбора и транслировать его в язык запросов 1С.
Это происходит, когда условия отбора наложены на простые поля, которые напрямую присутствуют в наборе данных "Запрос".
Посмотрим на пример. Допустим, в схеме компоновки данных у нас есть простой запрос для получения номенклатуры:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения
ИЗ
Справочник.Номенклатура КАК Номенклатура
Пользователь в настройках отчета добавляет отбор: ЕдиницаИзмерения = "шт".
В этом случае СКД легко определит, что поле ЕдиницаИзмерения есть в источнике данных. Она проанализирует схему и сгенерирует итоговый запрос, который будет выглядеть примерно так:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ЕдиницаИзмерения = &П1
Где &П1 — это параметр, в который СКД передаст значение "шт". Этот запрос будет выполнен на стороне СУБД, и мы сразу получим отфильтрованный результат.
В некоторых ситуациях СКД не может встроить условие отбора в текст запроса. Тогда она сначала выполняет исходный запрос без этого условия, получает все данные, а затем программно фильтрует полученную таблицу значений. Это происходит в следующих случаях:
СтатусЗаказа, значение которого определяется функцией МойОбщийМодуль.ОпределитьСтатус(). Отбор по такому полю будет применен уже после выполнения основного запроса.ЛЕВОЕ СОЕДИНЕНИЕ в одном запросе, а как отдельные наборы в схеме, отборы по полям дочернего набора к родительскому могут применяться после получения данных из обоих источников.ГДЕ.ИМЕЮЩИЕ в SQL), оно также применяется после основной выборки и агрегации данных.Важный момент: если отбор применяется при постобработке, это может не только замедлить отчет, но и привести к неверным итогам, если в отчете используются иерархические группировки. Именно поэтому так важно понимать, на каком этапе сработал ваш фильтр.
Чтобы не гадать, а точно знать, был ли отбор включен в запрос, можно проанализировать итоговый текст запроса, который генерирует СКД. Рассмотрим основные способы.
Это стандартный и самый распространенный метод. В модуле отчета можно создать обработчик этого события и получить доступ к уже сформированному макету компоновки данных.
Посмотрим на пример кода в обработчике:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем настройки и схему компоновки
СхемаКомпоновкиДанных = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Создаем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// Выполняем компоновку макета
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
// Получаем текст запроса из первого набора данных
// И выводим его для анализа
ТекстЗапроса = МакетКомпоновкиДанных.НаборыДанных[0].Запрос;
Сообщить(ТекстЗапроса);
// Можно прервать дальнейшее выполнение, если нужен был только текст запроса
// СтандартнаяОбработка = Ложь;
КонецПроцедуры
После выполнения этого кода в окне сообщений вы увидите финальный текст запроса. Если в нем присутствует секция ГДЕ с вашими условиями — значит, отбор применился на уровне базы данных.
Однако, как показывает практика, иногда даже после этого в свойстве Запрос может не быть следов отборов. Это верный признак того, что СКД приняла решение применить их на этапе постобработки. Сам факт отсутствия условия в этом тексте — это уже ценная диагностическая информация.
Для более глубокого анализа можно использовать внешние обработки, такие как "Консоль системы компоновки данных" или "Консоль отчетов". Эти инструменты позволяют в интерактивном режиме загрузить схему и настройки, выполнить компоновку и посмотреть все промежуточные данные, включая итоговый XML макета и, конечно же, текст сгенерированного запроса.
Момент применения отборов в СКД — это не магия, а результат работы внутреннего оптимизатора платформы. Запомните ключевые правила:
ГДЕ запроса к базе данных для максимальной производительности.ПриКомпоновкеРезультата, получив его из скомпонованного макета.Понимание этих принципов поможет вам создавать не только правильные, но и быстрые отчеты, а также эффективно находить причины проблем с производительностью и логикой работы СКД.