Как эффективнее отобрать данные в запросе: внутреннее соединение или подзапрос в условии виртуальной таблицы

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

В практике разработки на платформе 1С:Предприятие часто возникает задача фильтрации данных виртуальных таблиц (например, СрезПоследних или Обороты) по определенному списку значений. Рассмотрим классическую ситуацию: необходимо получить накладные из периодического регистра сведений, оформленные по конкретному списку договоров. Существует несколько способов решения этой задачи, и выбор наиболее эффективного напрямую влияет на быстродействие системы, особенно при работе с крупными базами данных под управлением MS SQL Server или PostgreSQL.

Использование параметров виртуальной таблицы

Согласно общим методическим рекомендациям, наиболее предпочтительным вариантом является наложение условий непосредственно в параметрах виртуальной таблицы. Разберем, почему это важно. Когда мы указываем условие в параметре (например, &УсловиеДоговор), платформа стремится передать этот фильтр максимально глубоко в SQL-запрос. Это позволяет СУБД отсечь ненужные записи еще на этапе первичной выборки из физических таблиц регистра.

Рассмотрим пример правильного оформления условия в параметрах:


ВЫБРАТЬ
    РегистрСведенийСрезПоследних.Договор,
    РегистрСведенийСрезПоследних.Накладная
ИЗ
    РегистрСведений.СведенияОНакладных.СрезПоследних(&Период, Договор В (&СписокДоговоров)) КАК РегистрСведенийСрезПоследних

Если Договор является измерением регистра, то СУБД сможет эффективно использовать существующие индексы. Однако стоит помнить об ограничении: если &СписокДоговоров содержит огромное количество элементов, это может привести к деградации производительности или даже ошибке переполнения SQL-запроса.

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

Часто возникает дилемма: передать список через подзапрос в условии ГДЕ или использовать конструкцию В (ВЫБРАТЬ...) прямо в параметре виртуальной таблицы. Проанализируем технические нюансы работы СУБД в этих случаях:

  1. Проблема кардинальности: При использовании подзапроса оптимизатор СУБД часто не может точно предсказать количество строк, которое вернет этот вложенный запрос. Это превращает подзапрос в «черный ящик». В результате система может выбрать неоптимальный план выполнения, например, Nested Loops (вложенные циклы), что фатально для скорости на больших объемах данных.
  2. Преимущество временных таблиц: Если список договоров формируется динамически, лучше сначала поместить его во временную таблицу (ВТ). При создании ВТ в 1С (через команду ПОМЕСТИТЬ) СУБД автоматически собирает по ней статистику. Это позволяет оптимизатору «видеть» объем данных и строить правильные соединения.
  3. Индексация ВТ: При использовании временной таблицы крайне важно индексировать поле, по которому будет идти соединение или фильтрация.

Пример использования проиндексированной временной таблицы в параметре:


// Сначала помещаем список во временную таблицу ВТ_Договоры с индексацией
// Затем используем её в основном запросе
ВЫБРАТЬ
    Срез.Договор,
    Срез.Накладная
ИЗ
    РегистрСведений.СведенияОНакладных.СрезПоследних(&Период, Договор В (ВЫБРАТЬ Т.Договор ИЗ ВТ_Договоры КАК Т)) КАК Срез

Внутреннее соединение со срезом последних

Вариант с использованием ВНУТРЕННЕЕ СОЕДИНЕНИЕ со срезом последних также имеет право на жизнь, но он считается наиболее «опасным» для производительности, особенно в PostgreSQL. Выясним причину: виртуальная таблица СрезПоследних сама по себе является сложным вложенным запросом с группировками или оконными функциями на уровне SQL. Соединение одного сложного подзапроса с другим подзапросом или таблицей часто сбивает оптимизатор с толку.

Важный момент: Если вы все же используете соединение, убедитесь, что соединяемые поля типизированы. Соединение по полям составного типа или по полям типа ЛюбаяСсылка (например, Регистратор) приводит к лавинообразному росту количества соединений с таблицами метаданных, что может полностью остановить выполнение запроса.

Практические рекомендации по оптимизации

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

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

← На главную