Почему СКД медленно выводит данные из таблицы значений и как это ускорить?

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

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

Разберем детально, почему так происходит, проанализируем внутренние механизмы Системы Компоновки Данных (СКД) и выясним, как оптимизировать процесс формирования отчета.

Причина 1: Проблема получения представлений ссылочных типов

Это основная причина низкой производительности внешних наборов данных. Рассмотрим, как СКД работает с данными разных типов. Когда источником является Запрос к базе данных, платформа 1С на этапе генерации итогового SQL-запроса автоматически добавляет соединения (JOIN) к таблицам справочников или документов, чтобы получить текстовые представления (наименования, номера) для всех ссылочных полей. Это происходит одним пакетом на стороне сервера базы данных.

В случае с внешним набором данных (ТЗ) ситуация иная:

  1. Процессор компоновки получает "голую" таблицу, в которой лежат ссылки (УИДы).
  2. В момент вывода каждой строки в отчет системе необходимо отобразить не саму ссылку, а ее строковое представление.
  3. Если в настройках отчета не указано иное, СКД начинает обращаться к базе данных за представлением для каждой конкретной ссылки в каждой строке.

Это порождает классическую проблему N+1 запросов: вместо одного эффективного запроса система выполняет тысячи мелких обращений к БД в цикле. Даже наличие кэширования в современных версиях платформы 1С 8.3 не спасает на больших объемах данных, так как накладные расходы на вызов каждого запроса остаются существенными.

Причина 2: Избыточность данных и "умный" выбор полей

Проанализируем разницу в объеме обрабатываемой информации. Когда источником данных является объект БД (регистр), механизм СКД выполняет оптимизацию запроса: из базы выбираются только те поля, которые реально используются в текущих настройках компоновки (выбранные поля, отборы, группировки).

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

Причина 3: Почему индексация ТЗ не дает эффекта

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

Способ оптимизации 1: Передача представлений строками

Самый эффективный способ ускорить вывод ТЗ в СКД — избавить систему от необходимости ходить в базу за представлениями. Для этого мы можем заранее подготовить текстовые описания объектов. Рассмотрим, как это реализовать по шагам:

  1. В исходной ТаблицеЗначений добавим дополнительные колонки строкового типа для всех ссылочных полей (например, НоменклатураПредставление).
  2. Заполним эти колонки программно с помощью одного запроса с использованием ПРЕДСТАВЛЕНИЕ(Поле).
  3. В схеме компоновки данных (СКД) для соответствующего поля (например, Номенклатура) установим свойство "Выражение представления", указав в нем имя нашей новой строковой колонки.

Пример подготовки таблицы в коде:


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

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

В настройках поля Товар в СКД в поле "Выражение представления" пишем: ТоварПредставление. Теперь СКД просто возьмет готовую строку из таблицы, не обращаясь к базе данных.

Способ оптимизации 2: Строгое ограничение типов

Проанализируем типы колонок в вашей ТЗ. Если колонка имеет составной тип или тип ЛюбаяСсылка, СКД тратит дополнительное время на определение метаданных при обработке каждой ячейки. Посмотрим на пример правильного создания колонок:


// Плохо:
ТЗ.Колонки.Добавить("Документ"); // Тип не определен, будет "Произвольный"

// Хорошо:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
ОписаниеТиповСтр = Новый ОписаниеТипов(МассивТипов);
ТЗ.Колонки.Добавить("Документ", ОписаниеТиповСтр);

Чем строже определены типы данных во внешнем наборе, тем быстрее процессор компоновки сможет их типизировать во внутренних структурах.

Способ оптимизации 3: Предварительная фильтрация данных

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

Резюме

Если скорость вывода критична и данных много, использование промежуточного регистра сведений (как сделал автор темы) является оправданным архитектурным решением. Это позволяет переложить всю тяжелую работу по сортировке, группировке и получению представлений на SQL-сервер. Однако, если использование регистра невозможно, применение "Выражений представления" и строгая типизация колонок ТЗ позволят сократить время формирования отчета в несколько раз, приблизив его к скорости работы стандартных запросов.

← На главную