Как ускорить получение остатков по заказам в списке документов 1С:Управление торговлей 10.3?

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

При работе в конфигурациях на обычных формах, таких как 1С:Управление торговлей 10.3, разработчики часто сталкиваются с проблемой медленной прокрутки списков документов. Одной из наиболее типичных ситуаций является необходимость отображения актуального состояния заказа (например, есть ли по нему остатки в регистре накопления) непосредственно в форме списка. Если реализовать это «в лоб», интерфейс начинает «тормозить», а замер производительности показывает, что 90% времени тратится на один и тот же запрос к виртуальной таблице остатков.

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

Анализ исходной проблемы

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


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ВЫРАЗИТЬ(ЗаказыПокупателейОстатки.ЗаказПокупателя КАК Документ.ЗаказПокупателя) КАК ЗаказПокупателя
ИЗ
    РегистрНакопления.ЗаказыПокупателей.Остатки(, ЗаказПокупателя В (&МассивДокументов)) КАК ЗаказыПокупателейОстатки
ГДЕ
    ЗаказыПокупателейОстатки.КоличествоОстаток <> 0

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

Решение 1: Правильная настройка индексов регистра

Проанализируем структуру регистра накопления ЗаказыПокупателей. В системе 1С индексы для физических таблиц итогов строятся на основе измерений регистра. Важнейшее правило: порядок измерений в конфигураторе напрямую влияет на составной индекс в SQL Server.

Если измерение ЗаказПокупателя стоит в списке вторым или третьим, а в запросе не указаны значения для первых измерений (например, «Организация»), то SQL-сервер не сможет эффективно использовать индекс. Вместо операции Index Seek (поиск по индексу) будет выполнена операция Index Scan (просмотр всего индекса), что на больших объемах данных крайне медленно.

Для оптимизации выполним следующие действия:

  1. Откроем свойства регистра накопления в конфигураторе.
  2. Установим у измерения ЗаказПокупателя свойство Индексировать.
  3. По возможности переместим это измерение на первое место в списке измерений, если поиск по нему является наиболее приоритетным и частым.

Как показала практика, после индексации измерения время выполнения запроса может сократиться с нескольких секунд до сотых долей секунды (в рассматриваемом случае с 2.7 сек до 0.18 сек), что делает работу пользователя комфортной.

Решение 2: Оптимизация передачи параметров (Массив vs Временная таблица)

Часто возникает спор: как эффективнее передавать список документов в условие виртуальной таблицы — через массив или через временную таблицу? Рассмотрим оба варианта.

Если документов в массиве немного (до 50-100 штук), использование конструкции ЗаказПокупателя В (&МассивДокументов) вполне допустимо. Однако при увеличении количества ссылок SQL-план запроса может стать неоптимальным. В этом случае рекомендуется использовать временную таблицу с индексацией:


// 1. Помещаем ссылки во временную таблицу
ВЫБРАТЬ Ссылка КАК Заказ ПОМЕСТИТЬ ВТ_Фильтр ИЗ Документ.ЗаказПокупателя ГДЕ Ссылка В (&МассивДокументов) ИНДЕКСИРОВАТЬ ПО Заказ;

// 2. Используем ВТ в параметрах виртуальной таблицы
ВЫБРАТЬ
    ЗаказыПокупателейОстатки.ЗаказПокупателя
ИЗ
    РегистрНакопления.ЗаказыПокупателей.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ Заказ ИЗ ВТ_Фильтр)) КАК ЗаказыПокупателейОстатки
ГДЕ
    ЗаказыПокупателейОстатки.КоличествоОстаток <> 0;

Проанализируем ситуацию: использование временной таблицы позволяет SQL-серверу более точно построить план соединения таблиц. Однако стоит помнить, что создание ВТ само по себе требует ресурсов, поэтому для маленьких порций данных в событии ПриПолученииДанных обычный массив зачастую работает быстрее.

Решение 3: Работа с условиями виртуальной таблицы

Важно помнить разницу между параметрами виртуальной таблицы (условия в скобках) и предложением ГДЕ. Выясним причину, почему это важно:

В нашем случае условие по измерению ЗаказПокупателя обязательно должно быть внутри параметров виртуальной таблицы. А вот условие по ресурсу КоличествоОстаток <> 0 физически невозможно вынести в параметры, так как ресурсы не входят в индекс таблицы итогов. Поэтому оно остается в ГДЕ. Рассмотрим пример правильной структуры запроса:


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

Дополнительные рекомендации по ускорению списков

Если технической оптимизации запроса недостаточно, проанализируем архитектурные подходы:

  1. Кэширование данных. В модуле формы можно создать переменную типа Соответствие, куда будут сохраняться уже полученные остатки для заказов. При прокрутке списка назад программа сначала будет проверять наличие данных в кэше, не обращаясь к базе данных.
  2. Использование признака «Закрыт». Если бизнес-логика позволяет, в документ «Заказ покупателя» можно добавить реквизит ЗаказЗакрыт (индексируемый). При полном выполнении заказа или его отмене регламентным заданием или при проведении документов этот флаг устанавливается в Истина. Тогда в списке можно будет проверять этот флаг, вообще не обращаясь к регистру остатков, что обеспечит мгновенную работу.
  3. Проверка актуальности итогов. Убедимся, что итоги в базе данных рассчитаны по текущую дату. Если итоги «развалились» или сильно отстают, 1С начнет вычислять остатки динамически по таблице движений, что сведет на нет любую оптимизацию запроса.

Подведем итог: для оптимизации списков в УТ 10.3 первым делом проверьте индексацию измерений и их порядок. Это дает самый заметный прирост производительности без изменения кода конфигурации.

← На главную