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

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

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

Давайте подробно разберем, какие преимущества дает использование метода ВыполнитьПакет() и почему в большинстве типовых конфигураций (например, в УТ 11 или ERP) используется именно этот подход.

1. Снижение накладных расходов на взаимодействие Клиент-Сервер и Сервер-СУБД

Главный аргумент в пользу пакетного запроса — это производительность, связанная с сетевыми задержками и количеством обращений (round-trips).

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

  1. Если код выполняется на клиенте (например, в толстом клиенте), каждый вызов Запрос.Выполнить() инициирует отдельное обращение к серверу приложений 1С. Если у вас 5 запросов, это 5 "путешествий" данных по сети. Метод Запрос.ВыполнитьПакет() делает это за один раз.
  2. Еще более важный момент происходит между сервером 1С и SQL-сервером. При использовании пакета платформа формирует один большой SQL-скрипт (batch), разделенный символами ;, и отправляет его СУБД.

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

2. Упрощенная работа с временными таблицами

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

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


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

// Первый запрос - помещаем данные
Запрос.Текст = "ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ...";
Запрос.Выполнить();

// Второй запрос - используем данные
Запрос.Текст = "ВЫБРАТЬ ... ИЗ ВТ ...";
Результат = Запрос.Выполнить();

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


Запрос.Текст = "
|ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ ИЗ ...
|;
|ВЫБРАТЬ ... ИЗ ВТ ...";

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

3. "Проблема индексов" и как ее решать

В обсуждении часто упоминается неудобство пакетных запросов: результат метода ВыполнитьПакет() — это массив. Если мы вставляем новый запрос в середину пакета, индексы массива сдвигаются (было Результаты[1], стало Результаты[2]), и приходится переписывать код обработки результатов.

Однако этот недостаток легко обходится правильным проектированием текста запроса. Давайте применим инструкцию УНИЧТОЖИТЬ.

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

Запросы, которые выполняют только помещение во временную таблицу (ПОМЕСТИТЬ) или уничтожение (УНИЧТОЖИТЬ), не возвращают результат в итоговый массив пакета (или возвращают пустой элемент, который можно игнорировать, если грамотно структурировать финальную выборку).

Лучшая практика — делать так, чтобы пакет возвращал результаты только в тех частях, которые реально нужны во встроенном языке.

4. Удобство отладки и Консоль запросов

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

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

5. Транзакционная целостность и согласованность

Хотя сам по себе ВыполнитьПакет() не открывает явную транзакцию (если вы не сделали это через НачатьТранзакцию), он обеспечивает лучшую согласованность данных (Read Consistency) в рамках одного вызова. Оптимизатор СУБД видит весь батч целиком и может построить более оптимальный план выполнения, понимая, как используются данные.

Резюме

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

Преимущества:

Когда использовать отдельные запросы? Лишь в редких случаях, когда логика выполнения второго запроса зависит от анализа данных, полученных в первом, на стороне приложения 1С (например: "Если в первом запросе сумма > 100, то выполняем второй запрос по одной логике, иначе — формируем совершенно другой текст запроса"). Но даже в этом случае часто можно использовать ВЫБОР КОГДА внутри самого запроса.

← На главную