Почему обращение к полям через точку тормозит запрос в 1С и как это оптимизировать

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При разработке на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда простой и логичный запрос начинает выполняться непозволительно долго. Особенно остро эта проблема проявляется в файловом варианте работы базы данных. Рассмотрим классический случай: выборка данных из табличной части документа с получением дополнительных реквизитов через ссылку (разыменование). Если без обращения к реквизитам справочника запрос «летает» (0.5 сек), а с ними — «зависает» (5-7 сек), значит, мы столкнулись с особенностями работы оптимизатора запросов и механизмом LEFT JOIN.

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

Выясним причину: механизм разыменования ссылок

Когда мы пишем в тексте запроса конструкцию вида расходнаяНакладнаятовары.товар.полнНаименование, платформа 1С автоматически преобразует это в левое соединение (LEFT OUTER JOIN) на уровне SQL-запроса. Если таких обращений несколько (например, к наименованию, производителю и импортеру), количество соединений увеличивается.

Проанализируем ситуацию: в файловой базе данных (движок 1CD) оптимизатор запросов значительно проще, чем в промышленных СУБД вроде MS SQL Server или PostgreSQL. Основная проблема заключается в том, что при наличии соединений и условий в секции ГДЕ, файловая СУБД часто сначала пытается выполнить соединение всех строк таблиц, а уже потом накладывает фильтр. Если в табличной части документов сотни тысяч строк, а в справочнике товаров — десятки тысяч, система пытается построить в памяти гигантскую временную таблицу, что и вызывает тормоза.

Ситуация усугубляется, если условие фильтрации также идет «через точку», например: ГДЕ расходнаяНакладнаятовары.Ссылка.WBRegId = &WBRegId. В этом случае для каждой строки табличной части система вынуждена обращаться к основной таблице документа, чтобы проверить значение реквизита шапки.

Решение №1: Использование временных таблиц для фильтрации

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

Рассмотрим пример оптимизированного запроса:


ВЫБРАТЬ
    расходнаяНакладнаятовары.Ссылка КАК Ссылка,
    расходнаяНакладнаятовары.НомерСтроки КАК НомерСтроки,
    расходнаяНакладнаятовары.товар КАК товар,
    ...
    расходнаяНакладнаятовары.Ссылка.WBRegId КАК WBRegId
ПОМЕСТИТЬ тбл_рез
ИЗ
    Документ.расходнаяНакладная.товары КАК расходнаяНакладнаятовары
ГДЕ
    расходнаяНакладнаятовары.Ссылка.WBRegId = &WBRegId
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    тбл_рез.Ссылка,
    тбл_рез.НомерСтроки,
    тбл_рез.товар,
    номенклатура.полнНаименование КАК товарполнНаименование,
    номенклатура.производитель КАК товарпроизводитель
ИЗ
    тбл_рез КАК тбл_рез
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК номенклатура
    ПО тбл_рез.товар = номенклатура.Ссылка

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

Решение №2: Предварительный отбор ссылок на документы

Как мы заметили ранее, условие расходнаяНакладнаятовары.Ссылка.WBRegId = &WBRegId заставляет систему «прыгать» из таблицы строк в таблицу шапок документов. В файловом режиме это очень дорогая операция. Попробуем оптимизировать еще сильнее, сначала отобрав саму ссылку на документ.

Разберем этот подход:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.расходнаяНакладная КАК Док
ГДЕ
    Док.WBRegId = &WBRegId
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ТЧ.Ссылка,
    ТЧ.товар,
    ТЧ.товар.полнНаименование
ИЗ
    Документ.расходнаяНакладная.товары КАК ТЧ
ГДЕ
    ТЧ.Ссылка В (ВЫБРАТЬ Ссылка ИЗ ВТ_Документы)

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

Решение №3: Обработка составных типов данных

Если реквизит товар имеет составной тип (например, Справочник.Номенклатура и Справочник.Услуги), то обращение через точку товар.полнНаименование заставит 1С сделать левое соединение со всеми таблицами, входящими в составной тип. Это критически замедляет запрос.

В таких случаях необходимо явно ограничивать тип с помощью функции ВЫРАЗИТЬ. Рассмотрим на примере:

ВЫРАЗИТЬ(расходнаяНакладнаятовары.товар КАК Справочник.Номенклатура).полнНаименование

Использование ВЫРАЗИТЬ подсказывает системе, что соединение нужно строить только с таблицей справочника Номенклатура, игнорируя остальные возможные типы. Это значительно упрощает план запроса.

Решение №4: Проверка индексов

Для того чтобы условие в ГДЕ работало быстро, поле, по которому идет отбор, должно быть проиндексировано. В нашем примере это реквизит WBRegId.

Важные моменты индексации:

  1. Убедитесь, что у реквизита WBRegId в метаданных установлено свойство Индексировать.
  2. Если вы часто фильтруете по табличной части, проверьте, проиндексировано ли поле Товар в ТЧ (хотя обычно 1С индексирует его автоматически при создании связи).
  3. В файловом режиме индексы порой могут «раздуваться» или работать неэффективно, поэтому регулярное тестирование и исправление базы (реиндексация) является обязательной процедурой.

Подведем итоги

Оптимизация запросов в 1С, особенно для файловых баз — это искусство управления соединениями. Проанализировав ситуацию, мы пришли к выводу, что «красивый» код с кучей точек в запросе часто превращается в «медленный» SQL-код.

Золотые правила оптимизации:

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

← На главную