Как ускорить выполнение запроса при левом соединении в 1С:Предприятие

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

При работе с платформой 1С:Предприятие, особенно в файловом варианте базы данных, разработчики часто сталкиваются с резким падением производительности запросов при использовании соединений. Ситуация, когда на небольшой базе запрос выполняется мгновенно, а на базе чуть большего объема (например, при увеличении справочника серий с 2 500 до 15 000 записей) «зависает» на десятки минут, является классическим примером неоптимальной работы планировщика запросов. Рассмотрим подробно, почему это происходит и как правильно оптимизировать такие запросы.

Анализ исходной проблемы и причин замедления

Рассмотрим типичный запрос, который вызывает сложности. В нем происходит обращение к табличной части документа и левое соединение со справочником. Основная проблема часто кроется в секции ГДЕ и обращении к реквизитам через точку.

Проанализируем основные причины «тормозов»:

  1. Разыменование полей (обращение через точку): Использование конструкций вида РеализацияТоваровУслугСерии.Ссылка.Дата заставляет систему выполнять неявное соединение табличной части с основной таблицей документов. В файловом режиме (SDBM) это может привести к тому, что фильтр по дате применится слишком поздно — уже после того, как система попытается сопоставить огромное количество строк.
  2. Особенности файлового движка: В отличие от SQL-серверов, файловая СУБД 1С часто использует алгоритм вложенных циклов (Nested Loops) без предварительной оптимизации выборки. Если левая таблица не ограничена, система перебирает все записи.
  3. Отсутствие индексов: Если поле, по которому идет соединение (например, Серия), не проиндексировано в метаданных табличной части, система выполняет полное сканирование таблицы (Full Table Scan).

Способ 1. Устранение неявных соединений (разыменования)

Первое, что мы должны сделать — это минимизировать обращения через точку в условиях запроса. Вместо того чтобы обращаться к дате через Ссылка.Дата в табличной части, правильнее сначала отобрать ссылки самих документов, а затем работать с их строками. Разберем, как изменить структуру запроса, чтобы помочь оптимизатору.

Если мы используем условие ГДЕ по полям шапки документа, обращаясь к ним из таблицы строк, система может сначала соединить ВСЕ строки ВСЕХ документов со справочником серий, и только потом отфильтровать результат. Чтобы этого избежать, используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей самого документа.

Посмотрим на пример правильной структуры:


ВЫБРАТЬ
    РеализацияСерии.Ссылка,
    Реализация.Номер,
    Реализация.Дата,
    РеализацияСерии.Серия,
    Серии.алкВидПродукции
ИЗ
    Документ.РеализацияТоваровУслуг.Серии КАК РеализацияСерии
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
    ПО РеализацияСерии.Ссылка = Реализация.Ссылка
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СерииНоменклатуры КАК Серии
    ПО РеализацияСерии.Серия = Серии.Ссылка
ГДЕ
    Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
    И Реализация.Партнер = &Партнер

Способ 2. Использование временных таблиц и индексации

Это самый надежный и «профессиональный» способ решения проблем производительности в 1С. Разделим сложный запрос на несколько простых этапов. Это позволит нам принудительно ограничить выборку данных на самом раннем этапе и подготовить индексы для быстрого соединения.

Выполним следующие шаги:

  1. Выберем ссылки документов во временную таблицу: Сначала отфильтруем только те документы, которые подходят под условия по дате и партнеру.
  2. Выберем данные табличной части во вторую временную таблицу: При этом будем использовать фильтр по первой временной таблице.
  3. Проиндексируем поле связи: Это критически важно для быстрого ЛЕВОГО СОЕДИНЕНИЯ.
  4. Выполним финальное соединение: Соединим подготовленные данные со справочником.

Рассмотрим пример реализации этого алгоритма:


// Шаг 1: Отбираем нужные документы
ВЫБРАТЬ
    Док.Ссылка КАК Ссылка,
    Док.Номер КАК Номер,
    Док.Дата КАК Дата
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.РеализацияТоваровУслуг КАК Док
ГДЕ
    Док.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
    И Док.Партнер = &Партнер
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Получаем только нужные строки ТЧ и индексируем поле Серия
ВЫБРАТЬ
    ТЧ.Ссылка КАК Ссылка,
    ВТ_Документы.Номер КАК Номер,
    ВТ_Документы.Дата КАК Дата,
    ТЧ.Серия КАК Серия,
    ТЧ.Количество КАК Количество
ПОМЕСТИТЬ ВТ_СтрокиДокументов
ИЗ
    Документ.РеализацияТоваровУслуг.Серии КАК ТЧ
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Документы КАК ВТ_Документы
    ПО ТЧ.Ссылка = ВТ_Документы.Ссылка
ИНДЕКСИРОВАТЬ ПО
    Серия
;

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

Почему это работает?

Проанализируем ситуацию: в исходном запросе система пыталась обработать всю таблицу серий (15 000 записей) и всю таблицу строк документов (которых может быть десятки тысяч). При использовании временных таблиц мы говорим системе: «Сначала возьми 1 нужный документ, достань из него 10 строк, положи их в отдельное место, пронумеруй (проиндексируй) серии и только потом найди для этих 10 серий информацию в справочнике».

Вместо перебора по принципу «каждый с каждым», система выполняет точечный поиск по индексу. Это сокращает время выполнения с минут до долей секунды.

Дополнительные рекомендации

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

Таким образом, использование временных таблиц и отказ от разыменования полей через точку в условиях ГДЕ — это ключ к стабильной и быстрой работе системы даже при росте объема данных.

← На главную