Как ускорить выполнение запроса к регистру накопления 1С?

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

Часто при разработке отчетов или обработок, которые должны выбирать большой объем данных из регистров накопления, разработчики сталкиваются с критическим падением производительности. Рассмотрим, как оптимизировать процесс получения данных, чтобы избежать «зависания» системы и сделать работу программы быстрой и эффективной.

Анализ проблемы: почему запрос работает медленно?

В исходном примере автор столкнулся с двумя классическими ошибками:

  1. Проблема N+1: выполнение запросов или обращение к данным через точку внутри цикла Пока. Каждое такое обращение делает отдельный запрос к базе данных.
  2. Неэффективная фильтрация: использование виртуальных таблиц с тяжелыми условиями в секции ГДЕ, а также вычисление логики складов прямо в цикле средствами языка 1С вместо того, чтобы передать эту работу серверу баз данных.

Шаг 1: Перенос логики из цикла в запрос

Самое важное правило оптимизации: старайтесь получить все необходимые данные одним запросом. Если вам нужно распределить количество по разным колонкам в зависимости от склада, используйте конструкцию ВЫБОР КОГДА прямо в языке запросов.

Рассмотрим, как это реализовать:


ВЫБРАТЬ
    Обороты.Склад,
    Обороты.Номенклатура,
    Обороты.КоличествоРасход,
    ВЫБОР 
        КОГДА Обороты.Склад = &Склад1 ТОГДА Обороты.КоличествоРасход 
        ИНАЧЕ 0 
    КОНЕЦ КАК СписаноСклад1,
    ВЫБОР 
        КОГДА Обороты.Склад = &Склад2 ТОГДА Обороты.КоличествоРасход 
        ИНАЧЕ 0 
    КОНЕЦ КАК СписаноСклад2
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(&Начало, &Конец, , ) КАК Обороты

Шаг 2: Избегаем лишних обращений в цикле

Никогда не обращайтесь к полям через точку в цикле, если эти данные можно получить сразу. Если вам нужен менеджер номенклатуры или единица измерения, добавьте ЛЕВОЕ СОЕДИНЕНИЕ со справочником Номенклатура прямо в запрос.

Вместо того чтобы в цикле писать Выборка.Номенклатура.ОтветственныйМенеджер, получите это значение на этапе формирования выборки:


ВЫБРАТЬ
    Обороты.Номенклатура,
    Обороты.Номенклатура.ОтветственныйМенеджерЗаПокупки КАК Менеджер,
    Обороты.Номенклатура.ЕдиницаХраненияОстатков КАК Единица
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(...) КАК Обороты

Шаг 3: Оптимизация виртуальных таблиц

Если запрос все равно работает долго, проанализируйте использование виртуальной таблицы Обороты. Если вам не требуются сложные агрегаты (начальные/конечные остатки), попробуйте выбирать данные из физической таблицы движений, либо максимально сузьте фильтр в параметрах виртуальной таблицы.

Используйте временные таблицы для фильтрации большого списка номенклатуры, чтобы СУБД могла построить оптимальный план выполнения:


ВЫБРАТЬ 
    Спр.Ссылка 
ПОМЕСТИТЬ втНоменклатура 
ИЗ Справочник.Номенклатура КАК Спр 
ГДЕ Спр.ВидНоменклатуры = &Материал;

ВЫБРАТЬ
    Обороты.Склад,
    Обороты.КоличествоРасход
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(
        &Начало, 
        &Конец, 
        Запись, 
        Номенклатура В (ВЫБРАТЬ ВТ.Ссылка ИЗ втНоменклатура КАК ВТ)
    ) КАК Обороты
ГДЕ
    Обороты.Регистратор ССЫЛКА Документ.ТребованиеНакладная

Итоговые рекомендации по оптимизации

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

← На главную