Как оптимизировать сложные запросы в 1С с помощью временных таблиц?

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

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

В чем заключается основная проблема вложенных запросов?

Когда мы используем вложенный запрос в секции ЛЕВОЕ СОЕДИНЕНИЕ или ГДЕ, планировщик запросов СУБД (будь то MS SQL Server или PostgreSQL) не всегда может эффективно определить статистику распределения данных. В результате создается неоптимальный план выполнения, что приводит к сканированию всей таблицы вместо поиска по индексу. Рассмотрим ситуацию: нам нужно получить остатки товаров только по списку определенных номенклатурных позиций, которые удовлетворяют сложному условию.

Проанализируем типичный пример «плохого» кода:


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

В данном случае СУБД может выполнить вложенный запрос для каждой строки основной таблицы, что критически замедлит выполнение. Выясним причину: отсутствие типизации и индексов для промежуточного результата.

Решение проблемы через временные таблицы

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

Разберем по шагам правильный алгоритм работы:

  1. Создаем объект МенеджерВременныхТаблиц.
  2. В первом запросе выбираем необходимые данные (например, список номенклатуры) во временную таблицу.
  3. Обязательно индексируем временную таблицу по полям, которые будут участвовать в соединениях.
  4. Во втором запросе соединяем временную таблицу с целевыми данными.

Посмотрим на пример реализации этого подхода в коде 1С:


// Создаем менеджер для хранения временных таблиц
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// Шаг 1: Подготовка списка фильтрации
Запрос.Текст = 
"ВЫБРАТЬ
|	Номенклатура КАК Ссылка
|ПОМЕСТИТЬ ВТ_СписокТоваров
|ИЗ
|	Справочник.Номенклатура
|ГДЕ
|	ВидНоменклатуры = &ВидТовара
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	Продажи.Номенклатура,
|	Продажи.КоличествоОборот
|ИЗ
|	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК Продажи
|ГДЕ
|	Продажи.Номенклатура В (ВЫБРАТЬ Ссылка ИЗ ВТ_СписокТоваров)";

Запрос.УстановитьПараметр("ВидТовара", ВидТовара);
Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецПериода);

Результат = Запрос.Выполнить();

Почему это работает быстрее?

Рассмотрим подробнее внутренние механизмы. При использовании временной таблицы с ключевым словом ПОМЕСТИТЬ, платформа 1С создает реальную физическую таблицу в базе данных (в базе tempdb для MS SQL). Это позволяет планировщику СУБД:

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


ВЫБРАТЬ
    Номенклатура КАК Ссылка
ПОМЕСТИТЬ ВТ_ТоварыДляАнализа
ИЗ
    Справочник.Номенклатура
ГДЕ
    ЭтоГруппа = ЛОЖЬ
ИНДЕКСИРОВАТЬ ПО
    Ссылка
;

После добавления инструкции ИНДЕКСИРОВАТЬ ПО последующие соединения с этой таблицей будут проходить практически мгновенно, так как СУБД будет использовать операцию Index Seek вместо Full Scan.

Типичные ошибки при работе с временными таблицами

Рассмотрим ситуации, которые могут свести на нет всю пользу от оптимизации:

  1. Избыточность данных. Не помещайте во временную таблицу все колонки «на всякий случай». Выбирайте только те поля, которые понадобятся для связей или вывода.
  2. Отсутствие индексации. Как уже упоминалось, для больших объемов данных отсутствие индекса может сделать запрос даже медленнее, чем он был до оптимизации.
  3. Длительное хранение. Если вы используете один МенеджерВременныхТаблиц для множества разных задач в рамках одной процедуры, не забывайте очищать ненужные таблицы, чтобы не переполнять системную базу tempdb. Используйте команду УНИЧТОЖИТЬ.

Пример уничтожения таблицы:


Запрос.Текст = "УНИЧТОЖИТЬ ВТ_СписокТоваров";
Запрос.Выполнить();

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

Особое внимание стоит уделить работе с виртуальными таблицами остатков и оборотов. В 1С крайне не рекомендуется выполнять соединения с виртуальными таблицами напрямую. Проанализируем ситуацию: если нам нужно получить остатки по конкретному списку договоров, правильнее сначала поместить список договоров во временную таблицу, а затем передать этот список в параметры виртуальной таблицы.

Разберем пример эффективного получения остатков:


// Сначала подготавливаем фильтр
Запрос.Текст = 
"ВЫБРАТЬ Ссылка ПОМЕСТИТЬ ВТ_Фильтр ИЗ Справочник.Договоры ГДЕ Организация = &Организация;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	Остатки.Счет,
|	Остатки.СуммаОстаток
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , , Договор В (ВЫБРАТЬ Ссылка ИЗ ВТ_Фильтр)) КАК Остатки";

Обратите внимание: мы передаем условие через В (ВЫБРАТЬ Ссылка ИЗ ВТ_Фильтр) непосредственно в параметры виртуальной таблицы. Это позволяет платформе 1С оптимизировать SQL-запрос еще на этапе обращения к итогам регистра, не вычитывая лишние данные в память сервера приложений.

Выводы и рекомендации

Мы выяснили, что временные таблицы — это мощный инструмент в руках разработчика 1С для управления производительностью системы. Рассмотрим основные правила, которые помогут вам писать быстрый код:

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

← На главную