При работе с крупными конфигурациями или сложными аналитическими отчетами разработчики часто сталкиваются с ситуацией, когда текст запроса разрастается до внушительных размеров — 1000 строк и более. В таких случаях может возникнуть странный эффект: запрос выполняется долго (например, 5 секунд), даже если данных в базе почти нет, а индексы настроены корректно. Самое примечательное, что даже при наличии синтаксической ошибки платформа «задумывается» на те же 5 секунд, прежде чем выдать сообщение об ошибке. Рассмотрим подробнее, почему это происходит и как это исправить.
Проанализируем ситуацию, описанную в теме. Если задержка происходит даже при возникновении ошибки, это верный признак того, что время тратится не на обращение к СУБД, а на трансляцию и синтаксический анализ запроса самой платформой 1С. Разберем по шагам, что происходит «под капотом»:
ЛЕВОЕ СОЕДИНЕНИЕ) и объединений (ОБЪЕДИНИТЬ ВСЕ) глубина этого дерева становится критической.Таким образом, мы имеем дело с проблемой «длинной компиляции». Чтобы вылечить эту «дичь», нужно упростить задачу для парсера платформы.
Это самый эффективный способ ускорить анализ запроса. Вместо того чтобы заставлять 1С строить одно гигантское дерево для 1000 строк кода, мы разделим его на логические этапы. Рассмотрим, как это сделать с помощью МенеджерВременныхТаблиц.
Когда запрос разбит на пакеты (разделенные символом ;), платформа анализирует каждую часть последовательно. Это значительно снижает нагрузку на оптимизатор. Выясним, как преобразовать ваш код:
// Создаем менеджер временных таблиц
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// Часть 1: Предварительный отбор данных во временную таблицу
Запрос.Текст =
"ВЫБРАТЬ
| Т.Ссылка КАК ДокументСсылка,
| Т.СуммаДокумента КАК Сумма
|ПОМЕСТИТЬ ВТ_ОсновныеДанные
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Т
|ГДЕ
| Т.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.Выполнить();
// Часть 2: Основная логика с использованием подготовленных данных
Запрос.Текст =
"ВЫБРАТЬ
| ВТ.ДокументСсылка,
| ВТ.Сумма,
| ЕСТЬNULL(ДопСведения.Значение, 0) КАК ДопПоле
|ИЗ
| ВТ_ОсновныеДанные КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения
| ПО ВТ.ДокументСсылка = ДопСведения.Объект";
Результат = Запрос.Выполнить().Выгрузить();
Важный момент: использование временных таблиц не только ускоряет парсинг, но и делает план выполнения в СУБД более предсказуемым, особенно в файловом режиме.
Если текст запроса формируется программно (динамически), проанализируем его на наличие лишних конструкций. Часто генераторы кода добавляют:
ГДЕ, которые дублируют друг друга.Помните: каждое лишнее поле в ВЫБРАТЬ — это дополнительная работа для парсера по проверке прав доступа, даже если RLS у вас отключен. Платформа все равно обязана проверить схему.
Чтобы понять, какая именно часть вашего 1000-строчного монстра тормозит, используйте профессиональные инструменты, такие как ИР (Инструменты Разработчика). Посмотрим на алгоритм действий:
Файловая база данных имеет свои пределы. Как было отмечено в обсуждении, файловые базы хороши для небольших внедрений или демонстраций. Если ваша бизнес-логика требует обработки запросов по 1000 строк с кучей проверок, проанализируем возможность перехода на MS SQL или PostgreSQL. Серверные СУБД гораздо лучше справляются с кэшированием планов выполнения. Если один и тот же сложный запрос выполняется часто, SQL-сервер сохранит его план, и повторные запуски (при использовании параметров) будут проходить мгновенно.
Сформулируем основные правила, которые помогут избежать пятисекундных задержек:
Запрос.УстановитьПараметр(). Это критически важно для механизмов кэширования планов.Проанализировав все способы, мы видим, что «лечение» заключается в декомпозиции кода. Разбив «слона» на кусочки с помощью временных таблиц, вы избавитесь от долгого ожидания компиляции и сделаете систему отзывчивой.