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