В какой момент СКД применяет отборы: на уровне запроса или после получения данных?

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

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

Основной принцип работы СКД: оптимизация

Система компоновки данных — это мощный инструмент, который не просто выполняет ваш запрос, но и старается его оптимизировать. Главный принцип этой оптимизации — перенести как можно больше вычислений и фильтрации на сторону СУБД. Это означает, что СКД всегда будет стремиться включить условия отбора непосредственно в текст запроса, добавляя их в секцию ГДЕ (WHERE).

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

Таким образом, момент применения отбора не является случайным или непредсказуемым. Он зависит от того, сможет ли СКД "понять" условие отбора и транслировать его в язык запросов 1С.

Сценарий 1: Отбор применяется на уровне запроса (оптимальный случай)

Это происходит, когда условия отбора наложены на простые поля, которые напрямую присутствуют в наборе данных "Запрос".

Посмотрим на пример. Допустим, в схеме компоновки данных у нас есть простой запрос для получения номенклатуры:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование,
    Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения
ИЗ
    Справочник.Номенклатура КАК Номенклатура

Пользователь в настройках отчета добавляет отбор: ЕдиницаИзмерения = "шт".

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


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование,
    Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.ЕдиницаИзмерения = &П1

Где &П1 — это параметр, в который СКД передаст значение "шт". Этот запрос будет выполнен на стороне СУБД, и мы сразу получим отфильтрованный результат.

Сценарий 2: Отбор применяется при постобработке (менее оптимальный случай)

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

  1. Отбор по вычисляемому полю со сложным выражением. Особенно если в выражении используются функции общих модулей или встроенного языка, которые не могут быть транслированы в язык запросов. Например, у вас есть вычисляемое поле СтатусЗаказа, значение которого определяется функцией МойОбщийМодуль.ОпределитьСтатус(). Отбор по такому полю будет применен уже после выполнения основного запроса.
  2. Отбор по полю из связанного набора данных. Если наборы данных связаны не через ЛЕВОЕ СОЕДИНЕНИЕ в одном запросе, а как отдельные наборы в схеме, отборы по полям дочернего набора к родительскому могут применяться после получения данных из обоих источников.
  3. Сложные условия отбора. Некоторые нестандартные условия, которые пользователь может задать в настройках, СКД может оказаться не в силах преобразовать в конструкцию ГДЕ.
  4. Условия на агрегатные функции в группировках. Если вы накладываете условие на сгруппированные данные (аналог секции ИМЕЮЩИЕ в SQL), оно также применяется после основной выборки и агрегации данных.

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

Как точно узнать, где был применен отбор?

Чтобы не гадать, а точно знать, был ли отбор включен в запрос, можно проанализировать итоговый текст запроса, который генерирует СКД. Рассмотрим основные способы.

Способ 1: Анализ в обработчике события `ПриКомпоновкеРезультата`

Это стандартный и самый распространенный метод. В модуле отчета можно создать обработчик этого события и получить доступ к уже сформированному макету компоновки данных.

Посмотрим на пример кода в обработчике:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем настройки и схему компоновки
    СхемаКомпоновкиДанных = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();

    // Создаем компоновщик макета
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

    // Выполняем компоновку макета
    МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    // Получаем текст запроса из первого набора данных
    // И выводим его для анализа
    ТекстЗапроса = МакетКомпоновкиДанных.НаборыДанных[0].Запрос;
    Сообщить(ТекстЗапроса);

    // Можно прервать дальнейшее выполнение, если нужен был только текст запроса
    // СтандартнаяОбработка = Ложь;

КонецПроцедуры

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

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

Способ 2: Использование специализированных инструментов

Для более глубокого анализа можно использовать внешние обработки, такие как "Консоль системы компоновки данных" или "Консоль отчетов". Эти инструменты позволяют в интерактивном режиме загрузить схему и настройки, выполнить компоновку и посмотреть все промежуточные данные, включая итоговый XML макета и, конечно же, текст сгенерированного запроса.

Подведем итог

Момент применения отборов в СКД — это не магия, а результат работы внутреннего оптимизатора платформы. Запомните ключевые правила:

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

Понимание этих принципов поможет вам создавать не только правильные, но и быстрые отчеты, а также эффективно находить причины проблем с производительностью и логикой работы СКД.

← На главную