Почему отчет на СКД формируется медленно, если запрос в консоли выполняется за секунды?

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

Довольно часто разработчики сталкиваются с ситуацией, когда сложный отчет на базе системы компоновки данных (СКД) в конфигурациях на платформе 1С:Предприятие 8.3 (например, 1С:Управление торговлей 11) формируется несколько минут. При этом проверка исходного текста запроса в консоли запросов показывает моментальный результат — от 2 до 5 секунд. Разберем детально, почему возникает такая разница в производительности, где на самом деле теряется время и какими способами можно ускорить формирование отчета.

Причины медленной работы отчета на СКД

Если текст запроса идентичен, а время исполнения отличается в десятки раз, задержка кроется не в выборке данных СУБД, а во внутренних механизмах платформы 1С и СКД. Проанализируем основные факторы:

  1. Неявное получение представлений ссылочных типов. Когда в СКД в поля отчета выводится ссылка на объект (справочник, документ), платформа для каждой строки выполняет отдельное обращение за строковым представлением объекта. Если в результате отчета тысячи строк с уникальными ссылками, генерируются тысячи мелких неявных запросов к СУБД.
  2. Ресурсоемкий расчет итогов и группировок процессором компоновки. В отличие от прямого запроса, где группировка и агрегатные функции выполняются оптимизированным движком СУБД, СКД производит расчет ресурсов, пользовательских полей и многоуровневых группировок собственными алгоритмами в оперативной памяти сервера 1С.
  3. Вывод и форматирование табличного документа. Отрисовка ячеек объектом ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент занимает значительную часть времени, если включен автоматический расчет ширины колонок, перенос текста по словам, автовысота строк или сложное условное оформление.
  4. Фоновые задания и накладные расходы БСП. В типовых конфигурациях отчеты формируются в фоновом режиме через подсистему «Варианты отчетов». Время тратится на запуск фонового задания, передачу настроек, сериализацию табличного документа во временное хранилище и его передачу на клиент.
  5. Работа с временными файлами на сервере. При обработке больших объемов данных СКД использует дисковый кэш в системной папке временных файлов сервера 1С. Медленный диск или блокировка этих файлов антивирусным ПО вызывают существенные паузы.

Способ 1. Получение данных запросом в таблицу значений с передачей в СКД

Если отчет содержит специфическую логику или СКД выполняет избыточные трансформации запроса, эффективным решением является предварительное выполнение запроса средствами встроенного языка 1С, выгрузка результата в объект ТаблицаЗначений и передача этой таблицы в СКД в качестве внешнего набора данных. В этом случае за СКД остается только вывод в макет и управление оформлением.

Рассмотрим пример программного формирования отчета через внешний набор данных:


// Создаем и выполняем исходный запрос
Запрос = Новый Запрос;
Запрос.Текст = 
	"ВЫБРАТЬ
	|	ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
	|	ТоварыНаСкладахОстатки.Склад КАК Склад,
	|	ТоварыНаСкладахОстатки.ВНаличииОстаток КАК Количество
	|ИЗ
	|	РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки";

Запрос.УстановитьПараметр("Период", ТекущаяДата());
ТаблицаДанных = Запрос.Выполнить().Выгрузить();

// Подготавливаем компоновку данных
СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

// Заполняем внешний набор данных
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("НаборДанныхТаблица", ТаблицаДанных);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);

ТабличныйДокумент = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Такой подход исключает вмешательство СКД в оптимизацию запроса и существенно сокращает время выполнения.

Способ 2. Оптимизация схемы компоновки данных

Если требуется сохранить стандартную работу отчета без перехода на внешние наборы данных, проанализируем настройки самой схемы компоновки:

  1. Отключение автозаполнения полей. На вкладке «Наборы данных» снимите флаг Автозаполнение. Это предотвратит автоматическое добавление платформой лишних полей, таблиц и соединений в итоговый SQL-запрос. Все используемые поля, группировки и отборы укажите вручную в свойствах набора данных.
  2. Явное получение строковых представлений. Чтобы исключить единичные обращения за наименованиями объектов, используйте в запросе функцию ПРЕДСТАВЛЕНИЕ(ПолеСсылка) или обращайтесь к реквизиту напрямую (например, Номенклатура.Наименование КАК НоменклатураНаименование).
  3. Оптимизация параметров табличного документа. На вкладке «Настройки» в разделе «Другие настройки» установите фиксированные значения ширины колонок и отключите автоподбор ширины. Минимизируйте количество условий в блоке «Условное оформление».

Способ 3. Пошаговый замер серверных этапов формирования

Чтобы точно определить, на каком шаге происходит замедление, выполним замер производительности программного кода компоновки. Разделим процесс на ключевые операции:


// Шаг 1: Формирование макета компоновки
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки());
ВремяМакета = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;

// Шаг 2: Инициализация процессора компоновки и выборка данных
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ВремяИнициализации = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;

// Шаг 3: Вывод данных в результирующий табличный документ
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
ВремяВывода = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;

ЗаписьЖурналаРегистрации("ЗамерСКД", УровеньЖурналаРегистрации.Информация,,,
	СтрШаблон("Макет: %1 мс, Инициализация: %2 мс, Вывод: %3 мс", ВремяМакета, ВремяИнициализации, ВремяВывода));

Если задержка сосредоточена на этапе вывода (ПроцессорВывода.Вывести()), проблема заключается в отрисовке ячеек и оформлении. Если на этапе инициализации — дело в неявных запросах или медленной обработке итогов платформой.

Способ 4. Проверка серверной инфраструктуры

Если программный замер показывает, что сам код СКД выполняется быстро, а общее время ожидания в пользовательском интерфейсе велико, проверим системное окружение:

  1. Исключения антивируса. Убедимся, что рабочий каталог кластера серверов srvinfo и системный каталог временных файлов операционной системы (папка Temp пользователя, под которым работает служба ragent) добавлены в исключения антивирусного сканера.
  2. Нагрузка на менеджер кластера. В высоконагруженных базах запуск фоновых заданий отчетов может ожидать свободного потока в очереди сервиса заданий. Проверьте распределение сервисов по рабочим серверам кластера 1С.
← На главную