В чем преимущества использования пакетных запросов в 1С и зачем они нужны?

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

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

1. Сокращение сетевых накладных расходов (Network Round-Trip)

Рассмотрим, как происходит физическое взаимодействие между кластером серверов 1С (процессом rphost) и сервером СУБД (MS SQL Server, PostgreSQL и др.):

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

2. Удобство разработки, поддержки и использования конструктора запросов

С точки зрения поддержки кода пакетный запрос предоставляет значительные удобства:

  1. Работа в конструкторе: весь алгоритм сбора данных (создание временных таблиц, их индексация, агрегация и получение финальных выборок) доступен в едином окне Конструктора запросов на вкладке «Пакет запросов».
  2. Простая отладка через консоль запросов: текст пакетного запроса можно целиком скопировать в консоль запросов, передать параметры и сразу проанализировать результаты каждого шага. В случае с разрозненными фрагментами кода и динамической склейкой строк приходится вручную собирать текст в отладчике.
  3. Замена громоздких вложенных запросов: разбиение сложной логики на последовательные шаги пакета с промежуточными временными таблицами делает код в разы читаемее, чем использование многоуровневых вложенных подзапросов с десятками соединений.

3. Работа с временными таблицами без лишнего кода

Выясним, где физически хранятся временные таблицы и как ими управлять. Временные таблицы всегда создаются и хранятся на стороне СУБД (например, в базе tempdb для MS SQL Server), независимо от того, используется ли МенеджерВременныхТаблиц или пакетный запрос.

Преимущество пакета заключается в автоматическом управлении жизненным циклом таких таблиц:

  1. Если не подключен явный МенеджерВременныхТаблиц, область видимости и время жизни временных таблиц ограничены выполнением данного пакета. После завершения запроса ресурсы на стороне СУБД освобождаются автоматически.
  2. При использовании объекта МенеджерВременныхТаблиц в явном виде временные таблицы продолжают занимать память и дисковое пространство СУБД до тех пор, пока менеджер не будет уничтожен или закрыт сборщиком мусора, либо пока не будет выполнен явный запрос на их удаление (УНИЧТОЖИТЬ ВТ_ИмяТаблицы).
  3. Внутри пакета запросов можно сразу создать индекс по полям соединения с помощью конструкции ИНДЕКСИРОВАТЬ ПО, что существенно ускоряет последующие соединения.

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


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

Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());

// Получаем массив результатов для каждого запроса пакета
МассивРезультатов = Запрос.ВыполнитьПакет();

ТаблицаОстатковИЦен = МассивРезультатов[1].Выгрузить();
ТаблицаЗаказов = МассивРезультатов[2].Выгрузить();

4. Методы выполнения пакетов и работа с результатами

Платформа 1С предоставляет три способа выполнения пакетных запросов в зависимости от требуемой задачи:

  1. Запрос.Выполнить() — исполняет весь пакет на сервере СУБД, но возвращает объект РезультатЗапроса только для самого последнего запроса в пакете. Это наиболее экономный по оперативной памяти вариант, если промежуточные выборки в коде 1С не требуются.
  2. Запрос.ВыполнитьПакет() — возвращает массив результатов (Массив). Позиция каждого элемента строго соответствует номеру запроса в пакете. При этом запросы, создающие временные таблицы, возвращают пустой результат, а инструкции УНИЧТОЖИТЬ возвращают Неопределено.
  3. Запрос.ВыполнитьПакетСПромежуточнымиДанными() — возвращает реальные выборки даже для промежуточных временных таблиц, что крайне полезно при профилировании и отладке сложных расчетов.

Когда все же оправдано разделение на отдельные запросы?

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

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