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

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

При получении данных из регистров накопления разработчики 1С часто сталкиваются с существенным замедлением работы запросов. Проблема особенно проявляется, когда выборка строится на связке документа-основания и связанных с ним ордерных документов через виртуальные таблицы. Разберем, почему запрос работает медленно и как правильно организовать выборку данных в конфигурациях на платформе 1С:Предприятие.

Анализ исходного запроса и причин низкой производительности

Рассмотрим типовую ситуацию в конфигурации 1С:Управление торговлей 10.3. Задача разработчика — получить отрицательные остатки из регистра накопления ТоварыКПолучениюНаСклады по документу ПеремещениеТоваров. Поскольку прямая связь в регистре отсутствует, сначала выбираются документы РасходныйОрдерНаТовары, связанные с перемещением через реквизит ДокументПередачи, после чего выполняется соединение с виртуальной таблицей регистра.

Исходный запрос выглядит следующим образом:


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

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

  1. Отсутствие параметров у виртуальной таблицы: Виртуальная таблица ОстаткиИОбороты вызывается без ограничений по периоду и отборам (параметры ПериодНачала, ПериодКонца и Условие оставлены пустыми). СУБД рассчитывает остатки и обороты для абсолютно всех записей регистра за всю историю базы данных.
  2. Фильтрация в секции ГДЕ вместо параметров виртуальной таблицы: Условие из секции ГДЕ базового запроса применяется СУБД уже после формирования полной выборки из виртуальной таблицы и выполнения левого соединения. Платформа 1С не пробрасывает условия из ГДЕ внутрь подзапроса виртуальной таблицы автоматически.
  3. Периодичность «Регистратор»: Использование периодичности Регистратор вынуждает систему рассчитывать остатки на момент каждого движения регистра за всю историю. Это самая ресурсоемкая операция при работе с виртуальными таблицами остатков.

Варианты оптимизации запроса

Выясним, как изменить структуру запроса для достижения максимальной скорости выполнения.

Вариант 1. Использование временной таблицы и передача отбора в параметр виртуальной таблицы

Наиболее универсальный и правильный подход — сперва отбрать нужные документы во временную таблицу, проиндексировать её и передать результат в параметр Условие виртуальной таблицы.


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

ИНДЕКСИРОВАТЬ ПО
    Ссылка
;

ВЫБРАТЬ
    ВТ_Ордера.Ссылка КАК Ссылка,
    ТоварыКПолучениюНаСклады.ДокументПолучения,
    ТоварыКПолучениюНаСклады.Номенклатура,
    ТоварыКПолучениюНаСклады.ХарактеристикаНоменклатуры,
    ТоварыКПолучениюНаСклады.СерияНоменклатуры,
    ТоварыКПолучениюНаСклады.КоличествоОборот КАК Количество
ИЗ
    ВТ_Ордера КАК ВТ_Ордера
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыКПолучениюНаСклады.Обороты(, , Авто, Регистратор В (ВЫБРАТЬ ВТ_Ордера.Ссылка ИЗ ВТ_Ордера)) КАК ТоварыКПолучениюНаСклады
        ПО ВТ_Ордера.Ссылка = ТоварыКПолучениюНаСклады.Регистратор

При таком подходе платформа 1С передает условие фильтрации непосредственно в SQL-запрос СУБД. В результате обрабатываются только те записи регистра, которые относятся к найденным ордерам.

Вариант 2. Замена таблицы «ОстаткиИОбороты» на таблицу «Обороты» или «Остатки»

Рассмотрим назначение виртуальных таблиц:

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

Вариант 3. Использование отбора по измерениям регистра

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


ВЫБРАТЬ
    ТоварыКПолучениюНаСкладыОстатки.Номенклатура,
    ТоварыКПолучениюНаСкладыОстатки.ХарактеристикаНоменклатуры,
    ТоварыКПолучениюНаСкладыОстатки.СерияНоменклатуры,
    ТоварыКПолучениюНаСкладыОстатки.КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыКПолучениюНаСклады.Остатки(&МоментВремени, ДокументПолучения = &ПеремещениеТоваров) КАК ТоварыКПолучениюНаСкладыОстатки
ГДЕ
    ТоварыКПолучениюНаСкладыОстатки.КоличествоОстаток < 0

Рекомендации по повышению производительности

  1. Всегда передавайте условия отбора в параметры виртуальных таблиц, а не в секцию ГДЕ после соединения.
  2. Ограничивайте период выборки: Задавайте параметры ПериодНачала и ПериодКонца для виртуальных таблиц оборотов и остатков.
  3. Избегайте необоснованного применения периодичности «Регистратор» в таблице ОстаткиИОбороты. Если требуется срезать остаток на момент времени конкретного документа, используйте таблицу Остатки с передачей объекта МоментВремени.
← На главную