При разработке отчетов в системе 1С на базе Системы Компоновки Данных (СКД) разработчики часто сталкиваются с проблемой низкой производительности. Отчеты, которые обрабатывают большие объемы данных или используют сложные запросы с множеством соединений, могут формироваться неприемло долго, что снижает оперативность работы пользователей и общую эффективность системы. Особенно это актуально для отчетов типа "Заказ клиента" или когда требуется ускорение формирования отчета "Валовая прибыль предприятия", где необходимо агрегировать информацию из множества связанных таблиц.
В этой статье мы подробно рассмотрим, почему возникают такие проблемы, и предложим эффективное решение, позволяющее значительно ускорить формирование отчетов, используя возможности временных таблиц в запросах СКД. Мы будем действовать пошагово, вместе разбирая каждый аспект проблемы и предлагая конкретные примеры кода.
Давайте выясним, какие факторы чаще всего приводят к медленной работе отчетов:
ЛЕВОЕ СОЕДИНЕНИЕ (или других видов соединений) к объемным таблицам, это может сильно замедлить его выполнение. Каждое дополнительное соединение увеличивает комбинаторную сложность и объем промежуточных данных, которые необходимо обработать.В нашем случае, как мы видим из исходной проблемы, медленное формирование отчета "Заказ клиента" (на примере конфигурации 1С:Комплексная автоматизация 2.4 с управляемыми формами) было вызвано именно первым пунктом — сложным запросом с большим количеством соединений. Давайте рассмотрим пример такого запроса:
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК СсылкаЗаказа,
ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
ЗаказКлиентаТовары.Количество КАК Количество,
ЗаказКлиентаТовары.Сумма КАК Сумма,
Номенклатура.НаименованиеПолное КАК НоменклатураНаименование,
НоменклатураГруппыДоступа.Наименование КАК ГруппаДоступаНоменклатуры,
ВидыЦенНоменклатуры.Наименование КАК ВидЦены,
ДоговорыКонтрагентов.ВидДоговора КАК ВидДоговора,
Контрагенты.НаименованиеПолное КАК КонтрагентНаименование,
Организации.Наименование КАК ОрганизацияНаименование
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО ЗаказКлиентаТовары.Номенклатура = Номенклатура.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.НоменклатураГруппыДоступа КАК НоменклатураГруппыДоступа
ПО Номенклатура.ГруппаДоступа = НоменклатураГруппыДоступа.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыЦенНоменклатуры КАК ВидыЦенНоменклатуры
ПО ЗаказКлиентаТовары.ВидЦены = ВидыЦенНоменклатуры.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента
ПО ЗаказКлиентаТовары.Ссылка = ЗаказКлиента.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
ПО ЗаказКлиента.Договор = ДоговорыКонтрагентов.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ЗаказКлиента.Контрагент = Контрагенты.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Организации
ПО ЗаказКлиента.Организация = Организации.Ссылка
ГДЕ
ЗаказКлиента.Дата МЕЖДУ &ДатаНачало И &ДатаОкончание
И ЗаказКлиента.Проведен = ИСТИНА
В этом запросе мы видим множество соединений. Хотя сам по себе такой запрос логичен, при больших объемах данных он становится узким местом. Мы будем оптимизировать его с помощью временных таблиц.
Наиболее эффективный подход к оптимизации подобных запросов в СКД — это использование временных таблиц (ВТ). Временные таблицы позволяют разбить сложный запрос на несколько более простых, выполняя их последовательно. Сначала мы собираем основные данные в одну или несколько временных таблиц, а затем уже к этим "предварительно обработанным" данным присоединяем остальную информацию.
Как это работает:
ПОМЕСТИТЬ.Преимущество такого подхода заключается в том, что СУБД сначала обрабатывает только необходимый минимум данных, уменьшая объем промежуточных результатов. Дальнейшие соединения выполняются уже с гораздо меньшими таблицами (нашими временными таблицами), что существенно ускоряет процесс.
Давайте применим этот подход к нашему примеру с отчетом "Заказ клиента". Мы преобразуем единый, сложный запрос в пакет запросов с использованием временных таблиц.
На первом этапе мы соберем ключевую информацию о товарах из документов "Заказ клиента" и основные ссылки на связанные объекты (Номенклатура, ЗаказКлиента), а также применим фильтры по дате и проведенности. Это поможет нам максимально сократить набор данных для дальнейшей работы.
Обратите внимание, что здесь мы выбираем только те поля, которые нам точно понадобятся для дальнейших соединений или отображения, но пока стараемся избегать большого количества ЛЕВОЕ СОЕДИНЕНИЕ к справочникам, которые могут быть объемными. Мы используем оператор ПОМЕСТИТЬ ВТ_ОсновныеДанныеЗаказа для создания временной таблицы.
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК СсылкаЗаказа,
ЗаказКлиентаТовары.Номенклатура КАК НоменклатураСсылка,
ЗаказКлиентаТовары.Количество КАК Количество,
ЗаказКлиентаТовары.Сумма КАК Сумма,
ЗаказКлиента.Контрагент КАК КонтрагентСсылка,
ЗаказКлиента.Организация КАК ОрганизацияСсылка,
ЗаказКлиента.Договор КАК ДоговорСсылка,
ЗаказКлиентаТовары.ВидЦены КАК ВидЦеныСсылка
ПОМЕСТИТЬ ВТ_ОсновныеДанныеЗаказа
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента
ПО ЗаказКлиентаТовары.Ссылка = ЗаказКлиента.Ссылка
ГДЕ
ЗаказКлиента.Дата МЕЖДУ &ДатаНачало И &ДатаОкончание
И ЗаказКлиента.Проведен = ИСТИНА
;
В этом запросе мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ для связи табличной части Документ.ЗаказКлиента.Товары с шапкой документа Документ.ЗаказКлиента. Это гарантирует, что мы получим только данные по проведенным заказам в заданном диапазоне дат. Результат будет помещен во временную таблицу с именем ВТ_ОсновныеДанныеЗаказа.
Теперь, когда у нас есть компактная временная таблица с основными данными, мы можем создать второй запрос, который будет присоединять к ней дополнительные сведения из справочников. Этот запрос будет выполняться значительно быстрее, поскольку он работает с уже отфильтрованным и агрегированным набором данных.
ВЫБРАТЬ
ВТ_ОсновныеДанныеЗаказа.СсылкаЗаказа,
ВТ_ОсновныеДанныеЗаказа.НоменклатураСсылка,
ВТ_ОсновныеДанныеЗаказа.Количество,
ВТ_ОсновныеДанныеЗаказа.Сумма,
Номенклатура.НаименованиеПолное КАК НоменклатураНаименование,
НоменклатураГруппыДоступа.Наименование КАК ГруппаДоступаНоменклатуры,
ВидыЦенНоменклатуры.Наименование КАК ВидЦены,
ДоговорыКонтрагентов.ВидДоговора КАК ВидДоговора,
Контрагенты.НаименованиеПолное КАК КонтрагентНаименование,
Организации.Наименование КАК ОрганизацияНаименование
ИЗ
ВТ_ОсновныеДанныеЗаказа КАК ВТ_ОсновныеДанныеЗаказа
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО ВТ_ОсновныеДанныеЗаказа.НоменклатураСсылка = Номенклатура.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.НоменклатураГруппыДоступа КАК НоменклатураГруппыДоступа
ПО Номенклатура.ГруппаДоступа = НоменклатураГруппыДоступа.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыЦенНоменклатуры КАК ВидыЦенНоменклатуры
ПО ВТ_ОсновныеДанныеЗаказа.ВидЦеныСсылка = ВидыЦенНоменклатуры.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
ПО ВТ_ОсновныеДанныеЗаказа.ДоговорСсылка = ДоговорыКонтрагентов.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ВТ_ОсновныеДанныеЗаказа.КонтрагентСсылка = Контрагенты.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Организации
ПО ВТ_ОсновныеДанныеЗаказа.ОрганизацияСсылка = Организации.Ссылка
Как видим, во втором запросе мы используем ВТ_ОсновныеДанныеЗаказа как обычную таблицу. Все соединения теперь происходят с этой, уже небольшой, таблицей, а не с исходными объемными регистрами и справочниками. Это ключевой момент для повышения производительности.
Для того чтобы СКД правильно обработала наш пакет запросов, необходимо выполнить следующие настройки:
ПОМЕСТИТЬ, а второй (и последующие) — запросы, которые используют созданные временные таблицы.&ДатаНачало и &ДатаОкончание, которые мы используем в первом запросе для фильтрации данных перед помещением их во временную таблицу, будут автоматически передаваться СКД в первый запрос пакета. Это позволяет эффективно фильтровать данные на самом раннем этапе.Таким образом, мы добиваемся того, что сначала формируется минимально необходимый набор данных, а уже затем к нему добавляются дополнительные сведения. Этот подход позволяет сократить время формирования отчета с нескольких минут до нескольких секунд.
Помимо использования временных таблиц, существуют и другие методы, которые помогут нам улучшить производительность отчетов на СКД. Давайте рассмотрим их:
ПО) и накладываются фильтры (ГДЕ), являются индексированными в базе данных. Это позволяет СУБД быстро находить нужные записи.ОстаткиИОбороты, СрезПоследних), убедитесь, что правильно задаете их параметры (период, условия, измерения), чтобы получать минимально необходимый объем данных.Комбинируя эти подходы, мы можем добиться значительного улучшения производительности даже самых сложных отчетов на СКД.
Мы рассмотрели распространенную проблему медленного формирования отчетов на СКД в 1С и предложили проверенное решение с использованием временных таблиц. Разбив сложный запрос на несколько более простых и последовательных шагов, мы позволяем системе эффективно обрабатывать данные, существенно сокращая время формирования отчета. Этот метод является мощным инструментом в арсенале любого 1С-разработчика, стремящегося к созданию высокопроизводительных и отзывчивых решений.
Применяя данные рекомендации и примеры кода, вы сможете не только ускорить существующие отчеты, но и строить новые, изначально более эффективные аналитические инструменты.