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

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

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

Причины проблемы: Parameter Sniffing и неявное приведение типов

Проанализируем механизм взаимодействия платформы 1С с внешней СУБД (MS SQL Server, PostgreSQL, Oracle, MySQL) через драйвер ODBC:

  1. Неявное приведение типов (Implicit Conversion): В интерактивных консолях запросов значения параметров часто подставляются напрямую в виде литералов либо строго типизируются по метаданным. Когда же запрос формируется программно через метод УстановитьПараметр(), тип значения в 1С может незначительно отличаться от типа поля во внешней таблице (например, строка неограниченной длины вместо фиксированного VARCHAR(N), либо тип NVARCHAR вместо VARCHAR). В результате внешняя СУБД вынуждена на лету конвертировать тип каждого значения в таблице, из-за чего перестают работать индексы (происходит полный просмотр таблицы Table Scan / Index Scan вместо точечного поиска Index Seek).
  2. Эффект перехвата параметров (Parameter Sniffing): При первом обращении с параметризованным запросом оптимизатор СУБД строит и кэширует план выполнения под конкретное переданное значение. Если переданный параметр вызвал неявную конверсию или имел специфическую селективность, СУБД фиксирует неоптимальный план в кэше процедур для всех последующих сеансов выполнения из кода 1С.
  3. Различия в сессионных настройках: Интерактивные сеансы и серверные вызовы 1С могут использовать разные сессионные флаги СУБД (например, SET ANSI_NULLS, QUOTED_IDENTIFIER), что заставляет внешнюю базу компилировать изолированные планы запросов.

Способ 1. Явное приведение типов параметров в запросе

Разберем основной способ решения проблемы на уровне текста запроса 1С. Чтобы внешняя СУБД гарантированно использовала индекс, необходимо явно ограничить тип и длину передаваемого параметра с помощью функции ВЫРАЗИТЬ.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВнешняяТаблица.Идентификатор КАК Идентификатор,
    |	ВнешняяТаблица.Наименование КАК Наименование
    |ИЗ
    |	ВнешнийИсточникДанных.ВнешняяБД.Таблица.Контрагенты КАК ВнешняяТаблица
    |ГДЕ
    |	ВнешняяТаблица.Код = &КодКлиента";

Запрос.УстановитьПараметр("КодКлиента", СокрЛП(ПараметрКод));
Результат = Запрос.Выполнить();

Если поле Код во внешней базе имеет тип VARCHAR(20), неявная передача строки без явного ограничения типа приводит к сканированию всей таблицы. Исправим запрос, применив явное приведение типов:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВнешняяТаблица.Идентификатор КАК Идентификатор,
    |	ВнешняяТаблица.Наименование КАК Наименование
    |ИЗ
    |	ВнешнийИсточникДанных.ВнешняяБД.Таблица.Контрагенты КАК ВнешняяТаблица
    |ГДЕ
    |	ВнешняяТаблица.Код = ВЫРАЗИТЬ(&КодКлиента КАК Строка(20))";

Запрос.УстановитьПараметр("КодКлиента", СокрЛП(ПараметрКод));
Результат = Запрос.Выполнить();

Важно: Всегда проверяйте, чтобы тип в конструкции ВЫРАЗИТЬ в точности соответствовал типу и длине колонки в целевой СУБД.

Способ 2. Проверка описания метаданных внешнего источника данных

Проанализируем настройки конфигурации в ветке «Внешние источники данных»:

  1. Откроем свойства таблицы внешнего источника и перейдем к списку полей.
  2. Убедимся, что для каждого ключевого и поискового поля указана точная длина строк, чисел и признак поддержки NULL, идентичные структуре таблицы во внешней базе.
  3. Проверим свойство внешнего источника данных «Тип СУБД» (например, Microsoft SQL Server, PostgreSQL, MySQL). Платформа 1С формирует диалект SQL исходя из этого параметра. Неверно указанный тип СУБД приводит к генерации неэффективных SQL-конструкций через ODBC.

Способ 3. Оптимизация на стороне внешней СУБД

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

  1. Выполним обновление статистики по таблицам и индексам внешней базы (команды UPDATE STATISTICS для MS SQL Server или ANALYZE для PostgreSQL).
  2. В случае устойчивого проявления Parameter Sniffing на стороне MS SQL Server можно настроить подсказки оптимизатора (Plan Guide) с директивами OPTION (RECOMPILE) или OPTIMIZE FOR UNKNOWN для соответствующего параметризованного запроса.

Альтернативные архитектурные решения

Рассмотрим альтернативные варианты взаимодействия, если прямой запрос к таблицам ВИД по-прежнему вызывает задержки:

  1. Хранимые процедуры внешнего источника: Платформа 1С поддерживает добавление хранимых процедур и функций в состав внешнего источника данных. Перенос сложного запроса внутрь хранимой процедуры позволяет СУБД точно управлять планом выполнения и использовать локальные переменные для изоляции от Parameter Sniffing.
  2. Прямое подключение через COM/ADO: Если требуется обойти трансляцию запросов платформой 1С и передать сырой SQL-запрос со специфическими хинтами СУБД (например, WITH (NOLOCK)), можно воспользоваться объектом COMОбъект("ADODB.Connection").
  3. Предварительная фильтрация: При соединении таблиц 1С с внешними источниками платформа может полностью выгружать внешнюю таблицу во временные структуры сервера 1С. Чтобы этого избежать, всегда выполняйте предварительную выборку и фильтрацию данных внешнего источника отдельным запросом.
← На главную