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