Как значительно ускорить формирование отчета на СКД с помощью временных таблиц в 1С?

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

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

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

Основные причины низкой производительности отчетов на СКД

Давайте выясним, какие факторы чаще всего приводят к медленной работе отчетов:

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

В нашем случае, как мы видим из исходной проблемы, медленное формирование отчета "Заказ клиента" (на примере конфигурации 1С:Комплексная автоматизация 2.4 с управляемыми формами) было вызвано именно первым пунктом — сложным запросом с большим количеством соединений. Давайте рассмотрим пример такого запроса:


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК СсылкаЗаказа,
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
    ЗаказКлиентаТовары.Количество КАК Количество,
    ЗаказКлиентаТовары.Сумма КАК Сумма,
    Номенклатура.НаименованиеПолное КАК НоменклатураНаименование,
    НоменклатураГруппыДоступа.Наименование КАК ГруппаДоступаНоменклатуры,
    ВидыЦенНоменклатуры.Наименование КАК ВидЦены,
    ДоговорыКонтрагентов.ВидДоговора КАК ВидДоговора,
    Контрагенты.НаименованиеПолное КАК КонтрагентНаименование,
    Организации.Наименование КАК ОрганизацияНаименование
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
        ПО ЗаказКлиентаТовары.Номенклатура = Номенклатура.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.НоменклатураГруппыДоступа КАК НоменклатураГруппыДоступа
        ПО Номенклатура.ГруппаДоступа = НоменклатураГруппыДоступа.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыЦенНоменклатуры КАК ВидыЦенНоменклатуры
        ПО ЗаказКлиентаТовары.ВидЦены = ВидыЦенНоменклатуры.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента
        ПО ЗаказКлиентаТовары.Ссылка = ЗаказКлиента.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
        ПО ЗаказКлиента.Договор = ДоговорыКонтрагентов.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
        ПО ЗаказКлиента.Контрагент = Контрагенты.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Организации
        ПО ЗаказКлиента.Организация = Организации.Ссылка
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &ДатаНачало И &ДатаОкончание
    И ЗаказКлиента.Проведен = ИСТИНА

В этом запросе мы видим множество соединений. Хотя сам по себе такой запрос логичен, при больших объемах данных он становится узким местом. Мы будем оптимизировать его с помощью временных таблиц.

Ключевое решение: Использование временных таблиц в СКД

Наиболее эффективный подход к оптимизации подобных запросов в СКД — это использование временных таблиц (ВТ). Временные таблицы позволяют разбить сложный запрос на несколько более простых, выполняя их последовательно. Сначала мы собираем основные данные в одну или несколько временных таблиц, а затем уже к этим "предварительно обработанным" данным присоединяем остальную информацию.

Как это работает:

  1. Мы формируем первый запрос, который выбирает базовые данные из самых больших и "тяжелых" таблиц, применяя основные фильтры. Результат этого запроса помещается во временную таблицу с помощью оператора ПОМЕСТИТЬ.
  2. Затем мы создаем второй (и последующие) запросы, которые обращаются к уже сформированным временным таблицам, соединяя их с другими, возможно, менее объемными справочниками или регистрами.

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

Разбираем решение по шагам: Оптимизация запроса "Заказ клиента"

Давайте применим этот подход к нашему примеру с отчетом "Заказ клиента". Мы преобразуем единый, сложный запрос в пакет запросов с использованием временных таблиц.

Шаг 1: Формируем первую временную таблицу с основными данными

На первом этапе мы соберем ключевую информацию о товарах из документов "Заказ клиента" и основные ссылки на связанные объекты (Номенклатура, ЗаказКлиента), а также применим фильтры по дате и проведенности. Это поможет нам максимально сократить набор данных для дальнейшей работы.

Обратите внимание, что здесь мы выбираем только те поля, которые нам точно понадобятся для дальнейших соединений или отображения, но пока стараемся избегать большого количества ЛЕВОЕ СОЕДИНЕНИЕ к справочникам, которые могут быть объемными. Мы используем оператор ПОМЕСТИТЬ ВТ_ОсновныеДанныеЗаказа для создания временной таблицы.


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК СсылкаЗаказа,
    ЗаказКлиентаТовары.Номенклатура КАК НоменклатураСсылка,
    ЗаказКлиентаТовары.Количество КАК Количество,
    ЗаказКлиентаТовары.Сумма КАК Сумма,
    ЗаказКлиента.Контрагент КАК КонтрагентСсылка,
    ЗаказКлиента.Организация КАК ОрганизацияСсылка,
    ЗаказКлиента.Договор КАК ДоговорСсылка,
    ЗаказКлиентаТовары.ВидЦены КАК ВидЦеныСсылка
ПОМЕСТИТЬ ВТ_ОсновныеДанныеЗаказа
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента
        ПО ЗаказКлиентаТовары.Ссылка = ЗаказКлиента.Ссылка
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &ДатаНачало И &ДатаОкончание
    И ЗаказКлиента.Проведен = ИСТИНА
;

В этом запросе мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ для связи табличной части Документ.ЗаказКлиента.Товары с шапкой документа Документ.ЗаказКлиента. Это гарантирует, что мы получим только данные по проведенным заказам в заданном диапазоне дат. Результат будет помещен во временную таблицу с именем ВТ_ОсновныеДанныеЗаказа.

Шаг 2: Создаем второй запрос, использующий временную таблицу

Теперь, когда у нас есть компактная временная таблица с основными данными, мы можем создать второй запрос, который будет присоединять к ней дополнительные сведения из справочников. Этот запрос будет выполняться значительно быстрее, поскольку он работает с уже отфильтрованным и агрегированным набором данных.


ВЫБРАТЬ
    ВТ_ОсновныеДанныеЗаказа.СсылкаЗаказа,
    ВТ_ОсновныеДанныеЗаказа.НоменклатураСсылка,
    ВТ_ОсновныеДанныеЗаказа.Количество,
    ВТ_ОсновныеДанныеЗаказа.Сумма,
    Номенклатура.НаименованиеПолное КАК НоменклатураНаименование,
    НоменклатураГруппыДоступа.Наименование КАК ГруппаДоступаНоменклатуры,
    ВидыЦенНоменклатуры.Наименование КАК ВидЦены,
    ДоговорыКонтрагентов.ВидДоговора КАК ВидДоговора,
    Контрагенты.НаименованиеПолное КАК КонтрагентНаименование,
    Организации.Наименование КАК ОрганизацияНаименование
ИЗ
    ВТ_ОсновныеДанныеЗаказа КАК ВТ_ОсновныеДанныеЗаказа
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
        ПО ВТ_ОсновныеДанныеЗаказа.НоменклатураСсылка = Номенклатура.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.НоменклатураГруппыДоступа КАК НоменклатураГруппыДоступа
        ПО Номенклатура.ГруппаДоступа = НоменклатураГруппыДоступа.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыЦенНоменклатуры КАК ВидыЦенНоменклатуры
        ПО ВТ_ОсновныеДанныеЗаказа.ВидЦеныСсылка = ВидыЦенНоменклатуры.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
        ПО ВТ_ОсновныеДанныеЗаказа.ДоговорСсылка = ДоговорыКонтрагентов.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
        ПО ВТ_ОсновныеДанныеЗаказа.КонтрагентСсылка = Контрагенты.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Организации
        ПО ВТ_ОсновныеДанныеЗаказа.ОрганизацияСсылка = Организации.Ссылка

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

Шаг 3: Настройка СКД для работы с пакетом запросов и временными таблицами

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

  1. Создание нескольких наборов данных: В схеме компоновки данных вам потребуется создать не один, а два (или более) набора данных "Запрос". Первый набор данных будет содержать запрос с оператором ПОМЕСТИТЬ, а второй (и последующие) — запросы, которые используют созданные временные таблицы.
  2. Определение порядка выполнения: СКД автоматически определит порядок выполнения запросов в пакете, если они зависят друг от друга (т.е., если один запрос использует временную таблицу, созданную другим). Однако, всегда полезно убедиться, что логика построения запросов последовательна.
  3. Связывание полей: После того как вы добавите все наборы данных, убедитесь, что вторые и последующие наборы данных правильно "видят" поля временных таблиц. Эти поля будут доступны для выбора так же, как и поля обычных таблиц.
  4. Параметры СКД: Параметры, такие как &ДатаНачало и &ДатаОкончание, которые мы используем в первом запросе для фильтрации данных перед помещением их во временную таблицу, будут автоматически передаваться СКД в первый запрос пакета. Это позволяет эффективно фильтровать данные на самом раннем этапе.

Таким образом, мы добиваемся того, что сначала формируется минимально необходимый набор данных, а уже затем к нему добавляются дополнительные сведения. Этот подход позволяет сократить время формирования отчета с нескольких минут до нескольких секунд.

Дополнительные советы по оптимизации отчетов СКД

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

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

Комбинируя эти подходы, мы можем добиться значительного улучшения производительности даже самых сложных отчетов на СКД.

Заключение

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

Применяя данные рекомендации и примеры кода, вы сможете не только ускорить существующие отчеты, но и строить новые, изначально более эффективные аналитические инструменты.

← На главную