Как ускорить вывод колонки остатка в списке номенклатуры?

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

В высоконагруженных конфигурациях, таких как «Альфа-Авто», работа со списками номенклатуры часто становится узким местом. Пользователи жалуются на «подвисания» при поиске, прокрутке или просто при открытии формы. Основная причина — расчет остатков «на лету» внутри запроса динамического списка. Разберем детально, почему это происходит и как кардинально ускорить работу формы, используя программные методы оптимизации.

Почему поиск работает медленно: разница между Alt+F и строкой поиска

Проанализируем ситуацию, описанную автором темы. Поиск по подстроке (ввод текста в поле поиска) работает значительно медленнее, чем отбор по конкретному значению (Alt+F). Выясним причину такого поведения платформы 1С.

Когда мы используем Alt+F, платформа генерирует SQL-запрос с простым фильтром WHERE по индексированному полю (например, по ссылке или коду). SQL-сервер мгновенно находит нужные записи.

Однако при поиске по строке (полнотекстовый поиск или поиск по части слова) платформа анализирует все видимые колонки списка. Если в запросе динамического списка присутствует ЛЕВОЕ СОЕДИНЕНИЕ с виртуальной таблицей остатков, SQL-серверу приходится сначала выполнить это соединение для огромного количества записей справочника, рассчитать остатки, а уже затем применять фильтр LIKE %текст%. Это приводит к полному сканированию таблиц (Full Scan) и огромным задержкам, так как индексы перестают работать эффективно.

Решение 1: Ограничение использования поля в поиске и отборах

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

Посмотрим на пример кода, который ограничивает функционал поля динамического списка:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Находим поле в настройках компоновки данных динамического списка
    ПолеОстаток = Список.КомпоновщикНастроек.Настройки.ДоступныеПоляВыбора.Элементы.Найти("Остаток");
    
    Если ПолеОстаток <> Неопределено Тогда
        // Запрещаем группировку по этому полю
        ПолеОстаток.ОграничениеИспользования.Группировка = Истина;
        // Запрещаем сортировку (порядок)
        ПолеОстаток.ОграничениеИспользования.Порядок = Истина;
        // Запрещаем использование в условиях (отборах и поиске)
        ПолеОстаток.ОграничениеИспользования.Условие = Истина;
    КонецЕсли;

КонецПроцедуры

Этот метод позволяет «спрятать» тяжелое расчетное поле от механизма поиска. Платформа больше не будет пытаться искать введенную пользователем строку в колонке «Остаток», что существенно снизит нагрузку на сервер БД.

Решение 2: Использование события ПриПолученииДанныхНаСервере

Это самый эффективный и рекомендуемый метод для вывода расчетных данных в списках. Разберем по шагам его механику. Вместо того чтобы соединять справочник с регистрами в основном запросе списка (выбирая данные для тысяч записей), мы будем получать остатки только для тех 30–40 строк, которые фактически отображаются на экране пользователя.

  1. Подготовка запроса: Убираем из основного текста запроса динамического списка соединение с регистром остатков. Оставляем только выборку данных из справочника Номенклатура.
  2. Добавление колонки: В таблице формы (в элементе «Список») добавляем новую колонку (путь к данным не заполняем или создаем реквизит в объекте списка).
  3. Обработка события: Реализуем алгоритм в событии ПриПолученииДанныхНаСервере.

Рассмотрим пример реализации этого метода:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Получаем массив ссылок номенклатуры, которые сейчас видны на экране
    МассивСсылок = Строки.ПолучитьКлючи();
    
    // Одним запросом получаем остатки только по этим ссылкам
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Остатки.Номенклатура КАК Номенклатура,
        |   Остатки.КоличествоОстаток КАК Остаток
        |ИЗ
        |   РегистрНакопления.ОстаткиТоваровКомпании.Остатки(, Номенклатура В (&МассивСсылок)) КАК Остатки";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    РезультатЗапроса = Запрос.Выполнить().Выбрать();
    
    // Заполняем данные в отображаемых строках
    Пока РезультатЗапроса.Следующий() Цикл
        СтруктураСтроки = Строки[РезультатЗапроса.Номенклатура];
        // Указываем имя колонки, которую мы добавили на форму
        СтруктураСтроки.Данные.Остаток = РезультатЗапроса.Остаток;
    КонецЦикла;
    
КонецПроцедуры

Преимущество этого метода: Скорость работы списка становится практически мгновенной и не зависит от общего объема данных в регистре или справочнике. Мы запрашиваем ровно столько данных, сколько нужно пользователю в данный момент.

Важный нюанс: Помните, что при таком подходе по колонке «Остаток» нельзя будет сделать стандартную сортировку или отбор через платформенный механизм, так как данных нет в основной выборке ДинамическогоСписка.

Анализ конструкции {ГДЕ СправочникНоменклатура.Ссылка.*}

Выясним, за что отвечает эта конструкция в запросе. Это расширение языка запросов для Системы компоновки данных (СКД). Фигурные скобки обозначают необязательное условие. Платформа использует это место для подстановки пользовательских настроек (отборов).

Символ .* (звездочка через точку) крайне важен: он сообщает платформе, что пользователь может накладывать отборы не только по самой ссылке, но и по любому реквизиту номенклатуры (например, Номенклатура.Артикул или Номенклатура.ВидНоменклатуры). Платформа старается «прокинуть» эти отборы внутрь виртуальных таблиц для оптимизации, но в сложных запросах с множеством соединений (как в «Альфа-Авто») это не всегда спасает от медленной работы.

Дополнительные рекомендации по оптимизации

Проанализируем еще несколько факторов, которые могут замедлять вывод списка:

1. Сложные RLS (Rights Level Security): При использовании ВЫБРАТЬ РАЗРЕШЕННЫЕ 1С добавляет к вашему SQL-запросу условия проверки прав доступа. В «Альфа-Авто» правила RLS могут быть очень тяжелыми. Проверьте скорость работы под пользователем с полными правами. Если тормоза исчезли — проблему нужно искать в оптимизации ролей доступа.

2. Основная таблица: Убедитесь, что в свойствах динамического списка указана «Основная таблица» (Справочник.Номенклатура). Это позволяет платформе использовать механизм «ленивой загрузки» и корректно строить индексы.

3. Индексация в регистре: Проверьте, является ли измерение Номенклатура индексированным в регистре остатков. Обычно это так, но при значительных доработках конфигурации индекс могли случайно отключить.

Подводя итог, можно сказать, что для формы списка номенклатуры в «Альфа-Авто» оптимальным решением является использование ПриПолученииДанныхНаСервере для вывода остатков и цен, а для всех остальных реквизитов — использование стандартного динамического списка с четко определенной основной таблицей.

← На главную