Как правильно использовать временные таблицы в запросах 1С 8.3 для оптимизации производительности

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

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

Зачем нужны временные таблицы?

Разберем ситуацию: когда вложенный запрос выполняется несколько раз или содержит большой объем данных, СУБД (например, MS SQL Server или PostgreSQL) может некорректно построить план запроса. Это приводит к значительному замедлению работы системы. Рассмотрим основные преимущества использования временных таблиц:

  1. Оптимизация плана запроса: СУБД проще обрабатывать небольшие плоские таблицы, чем сложные иерархические вложенные конструкции.
  2. Повторное использование данных: Мы можем один раз выбрать данные во временную таблицу и обращаться к ней многократно в рамках одного сеанса работы с запросом.
  3. Индексация: В отличие от вложенных запросов, временные таблицы позволяют создавать индексы по ключевым полям, что критически важно для связей (JOIN).

Инициализация и использование Менеджера временных таблиц

Для работы с временными таблицами нам необходимо создать объект МенеджерВременныхТаблиц и связать его с объектом Запрос. Рассмотрим пример кода, в котором мы подготавливаем данные о продажах для дальнейшего анализа:


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

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

Запрос.Выполнить();

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

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

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


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

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

Выясним причину использования точки с запятой ;. Она разделяет отдельные запросы внутри одного пакета. Проанализируем ситуацию: в первом запросе мы отфильтровали данные и поместили их в ВТ_Фильтр, а во втором — соединили полученный результат с регистром цен. Это гораздо эффективнее, чем пытаться наложить условия и соединения в одном огромном запросе.

Очистка ресурсов и уничтожение временных таблиц

Многие программисты забывают, что временные таблицы занимают место в оперативной памяти сервера 1С и в базе tempdb на стороне СУБД. Если мы создаем таблицы в цикле или внутри часто вызываемых процедур, это может привести к переполнению ресурсов. Рассмотрим, как правильно уничтожать таблицы.

Существует два способа очистки:

  1. Автоматический: Временные таблицы удаляются сами при уничтожении объекта МенеджерВременныхТаблиц (когда переменная выходит из области видимости).
  2. Явный: Использование команды УНИЧТОЖИТЬ в тексте запроса. Это предпочтительный метод, если таблица больше не нужна в рамках текущего пакета.

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


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

Рекомендуем всегда уничтожать промежуточные таблицы, если ваш пакет запросов состоит из 10 и более шагов. Это позволяет поддерживать производительность системы на высоком уровне.

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

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

  1. Отсутствие индексации: Если вы соединяете временную таблицу с большой физической таблицей (например, РегистрБухгалтерии) и не проиндексировали поля связи во временной таблице, запрос может работать медленнее, чем обычный вложенный запрос.
  2. Помещение пустых таблиц: Если исходная выборка не содержит строк, 1С всё равно создаст структуру временной таблицы. Постоянное создание пустых таблиц создает лишнюю нагрузку на tempdb.
  3. Использование временных таблиц для 5-10 строк: В таких случаях накладные расходы на создание таблицы в СУБД превышают выигрыш от её использования. Для микро-выборок лучше использовать вложенные запросы или передачу массива в качестве параметра.

Советы по повышению эффективности

Посмотрим на дополнительные возможности. В 1С 8.3 появилась возможность передавать временные таблицы между разными объектами Запрос, если они используют один и тот же МенеджерВременныхТаблиц. Это позволяет выстраивать сложную цепочку вычислений, разбитую на разные модули и функции.

Также важно помнить про типизацию. Платформа 1С определяет типы полей временной таблицы автоматически на основе первого запроса. Если вы планируете использовать таблицу для объединения с другими данными, убедитесь, что типы полей строго определены (используйте ВЫРАЗИТЬ, если поле может содержать составной тип).

Разберем пример с явным приведением типов:


Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВЫРАЗИТЬ(ДокументОснование КАК Документ.РеализацияТоваровУслуг) КАК Ссылка,
    |   СуммаДокумента КАК Сумма
    |ПОМЕСТИТЬ ВТ_Данные
    |ИЗ
    |   Документ.ЗаказПокупателя";

В этом случае мы гарантируем, что в колонке Ссылка будут данные только одного типа, что значительно ускорит индексацию и последующие соединения на уровне SQL-сервера.

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

← На главную