При работе с платформой 1С:Предприятие, особенно в файловом варианте базы данных, разработчики часто сталкиваются с резким падением производительности запросов при использовании соединений. Ситуация, когда на небольшой базе запрос выполняется мгновенно, а на базе чуть большего объема (например, при увеличении справочника серий с 2 500 до 15 000 записей) «зависает» на десятки минут, является классическим примером неоптимальной работы планировщика запросов. Рассмотрим подробно, почему это происходит и как правильно оптимизировать такие запросы.
Рассмотрим типичный запрос, который вызывает сложности. В нем происходит обращение к табличной части документа и левое соединение со справочником. Основная проблема часто кроется в секции ГДЕ и обращении к реквизитам через точку.
Проанализируем основные причины «тормозов»:
РеализацияТоваровУслугСерии.Ссылка.Дата заставляет систему выполнять неявное соединение табличной части с основной таблицей документов. В файловом режиме (SDBM) это может привести к тому, что фильтр по дате применится слишком поздно — уже после того, как система попытается сопоставить огромное количество строк.Серия), не проиндексировано в метаданных табличной части, система выполняет полное сканирование таблицы (Full Table Scan).Первое, что мы должны сделать — это минимизировать обращения через точку в условиях запроса. Вместо того чтобы обращаться к дате через Ссылка.Дата в табличной части, правильнее сначала отобрать ссылки самих документов, а затем работать с их строками. Разберем, как изменить структуру запроса, чтобы помочь оптимизатору.
Если мы используем условие ГДЕ по полям шапки документа, обращаясь к ним из таблицы строк, система может сначала соединить ВСЕ строки ВСЕХ документов со справочником серий, и только потом отфильтровать результат. Чтобы этого избежать, используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей самого документа.
Посмотрим на пример правильной структуры:
ВЫБРАТЬ
РеализацияСерии.Ссылка,
Реализация.Номер,
Реализация.Дата,
РеализацияСерии.Серия,
Серии.алкВидПродукции
ИЗ
Документ.РеализацияТоваровУслуг.Серии КАК РеализацияСерии
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО РеализацияСерии.Ссылка = Реализация.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СерииНоменклатуры КАК Серии
ПО РеализацияСерии.Серия = Серии.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
И Реализация.Партнер = &Партнер
Это самый надежный и «профессиональный» способ решения проблем производительности в 1С. Разделим сложный запрос на несколько простых этапов. Это позволит нам принудительно ограничить выборку данных на самом раннем этапе и подготовить индексы для быстрого соединения.
Выполним следующие шаги:
ЛЕВОГО СОЕДИНЕНИЯ.Рассмотрим пример реализации этого алгоритма:
// Шаг 1: Отбираем нужные документы
ВЫБРАТЬ
Док.Ссылка КАК Ссылка,
Док.Номер КАК Номер,
Док.Дата КАК Дата
ПОМЕСТИТЬ ВТ_Документы
ИЗ
Документ.РеализацияТоваровУслуг КАК Док
ГДЕ
Док.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
И Док.Партнер = &Партнер
;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Получаем только нужные строки ТЧ и индексируем поле Серия
ВЫБРАТЬ
ТЧ.Ссылка КАК Ссылка,
ВТ_Документы.Номер КАК Номер,
ВТ_Документы.Дата КАК Дата,
ТЧ.Серия КАК Серия,
ТЧ.Количество КАК Количество
ПОМЕСТИТЬ ВТ_СтрокиДокументов
ИЗ
Документ.РеализацияТоваровУслуг.Серии КАК ТЧ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Документы КАК ВТ_Документы
ПО ТЧ.Ссылка = ВТ_Документы.Ссылка
ИНДЕКСИРОВАТЬ ПО
Серия
;
////////////////////////////////////////////////////////////////////////////////
// Шаг 3: Финальное соединение с справочником
ВЫБРАТЬ
ВТ_Строки.Ссылка,
ВТ_Строки.Номер,
ВТ_Строки.Дата,
ВТ_Строки.Серия,
ВТ_Строки.Количество,
Серии.алкВидПродукции
ИЗ
ВТ_СтрокиДокументов КАК ВТ_Строки
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СерииНоменклатуры КАК Серии
ПО ВТ_Строки.Серия = Серии.Ссылка
Проанализируем ситуацию: в исходном запросе система пыталась обработать всю таблицу серий (15 000 записей) и всю таблицу строк документов (которых может быть десятки тысяч). При использовании временных таблиц мы говорим системе: «Сначала возьми 1 нужный документ, достань из него 10 строк, положи их в отдельное место, пронумеруй (проиндексируй) серии и только потом найди для этих 10 серий информацию в справочнике».
Вместо перебора по принципу «каждый с каждым», система выполняет точечный поиск по индексу. Это сокращает время выполнения с минут до долей секунды.
Помимо оптимизации текста запроса, обратим внимание на следующие моменты:
Серия табличной части установлено свойство «Индексировать» (или «Индексировать с дополнительным упорядочиванием»).ТоварыНаСкладах или ДвиженияСерийТоваров), всегда отдавайте предпочтение им. Виртуальные таблицы 1С (ОстаткиИОбороты) оптимизированы на уровне платформы и работают быстрее, чем прямые запросы к табличным частям.Таким образом, использование временных таблиц и отказ от разыменования полей через точку в условиях ГДЕ — это ключ к стабильной и быстрой работе системы даже при росте объема данных.