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