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