В практике разработки на платформе 1С нередко возникает ситуация, когда сам запрос отчета в консоли запросов выполняется за считанные секунды или минуты, но при формировании отчета через Систему компоновки данных (СКД) процесс замирает на 0% и выполняется очень долго (иногда часами). Проблема может проявляться как после обновления платформы или переустановки сервера, так и при изменении пользовательских настроек отчета.
Рассмотрим подробно причины такого поведения, методику диагностики с помощью замера производительности и варианты устранения задержек при выводе данных.
Первым делом необходимо точно определить, на каком этапе система теряет время: на стороне СУБД при выполнении запроса или на этапе работы процессора вывода компоновки данных на сервере 1С.
Для проведения диагностики выполним следующие действия:
-debug).Если замер показывает, что основной массив времени уходит не на выполнение функции Заполнить() или исполнение SQL-запроса, а на цикл вывода элементов с помощью ПроцессорВывода.Вывести() или ПроцессорКомпоновки.Следующий(), значит, проблема кроется в алгоритмах компоновки макета и построения результата.
Одна из самых частых причин зависания вывода — создание огромного количества строк и колонок из-за некорректных настроек группировок. Если пользователь случайно задал группировку по детальным записям или добавил посекундную группировку в кросс-таблице, итоговый результат может содержать сотни тысяч мелких ячеек.
Проанализируем пример: если в результате компоновки формируется 300 000 элементов табличного документа, то даже при минимальных вычислениях на каждую ячейку отрисовка такого объема информации в памяти занимает длительное время. В подобных случаях необходимо проверить отборы и детальность группировок, установленные в настройках отчета.
При выгрузке данных СКД автоматически формирует представления для всех ссылочных полей (документов, справочников, перечислений), выводимых в отчет. Если для какого-либо объекта в конфигурации переопределен обработчик получения представления или используются тяжелые формулы разыменования, платформа выполняет отдельные обращения к базе данных или коду для каждой строки.
Чтобы избежать этой проблемы, разберем возможные решения:
Ссылка.Наименование или Ссылка.Представление. Это позволит получать строковое значение прямо из запроса без дополнительной обработки платформой.Использование в схеме СКД вычислимых полей, обращающихся к экспортным функциям общих модулей с серверными вызовами, резко снижает скорость формирования отчета. Если такая функция вызывается для каждой строки результата (например, 100 000 раз), время вывода вырастет экспоненциально.
Также к замедлению приводят сложные выражения ресурсов с использованием функций МАССИВ(), КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) или частые конструкторы ВЫБОР КОГДА ... ТОГДА при обработке больших массивов данных.
В этом случае рекомендуется перенести все возможные расчеты на уровень SQL-запроса, сформировав готовые числовые и строковые показатели заранее.
Если зависание отчетов началось строго после переустановки Windows Server или SQL Server при неизменном коде отчета, разберем системные факторы, влияющие на скорость вывода СКД:
Balanced (Сбалансированный). При однопоточных вычислениях СКД процессор не поднимает частоту до максимума. Переключение плана на High Performance (Высокая производительность) устраняет эту проблему.AppData\Local\Temp, каталоги временных файлов 1С, а также процессы rphost.exe и sqlservr.exe.tempdb имеет несколько файлов данных одинакового размера с достаточным шагом авторасширения.Для точной проверки скорости вывода компоновки можно заменить стандартный вывод результата в табличный документ на поэлементную обработку в коде. Посмотрим на пример кода, позволяющего замерить время обработки каждой записи:
СхемаКомпоновки = ПолучитьМакет("СхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ТабличныйДокумент = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.НачатьВывод();
Счетчик = 0;
Пока Истина Цикл
ЭлементРезультата = ПроцессорКомпоновки.Следующий();
Если ЭлементРезультата = Неопределено Тогда
Прервать;
КонецЕсли;
ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
Счетчик = Счетчик + 1;
Если Счетчик % 10000 = 0 Тогда
Сообщить("Выведено элементов: " + Формат(Счетчик, "ЧГ=0"));
КонецЕсли;
КонецЦикл;
ПроцессорВывода.ЗакончитьВывод();
Данный подход позволяет выявить момент, на котором тормозит вывод, проконтролировать реальное количество обработанных элементов результата и определить, не перегружает ли отчет оперативную память сервера.
Если отчет на СКД выполняется быстро в консоли запросов, но замирает при выводе пользователю: