Почему долго открывается форма подбора товара в клиент-серверном режиме и как ее ускорить?

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

При переходе с файловой базы на клиент-серверный вариант работы разработчики нередко сталкиваются с ситуацией, когда типовые формы начинают открываться в разы медленнее. Яркий пример — форма подбора номенклатуры в документах продажи (конфигурация «1С:Управление торговлей 11»), которая в файловом режиме может открываться за 2–4 секунды, а на сервере СУБД (особенно PostgreSQL) зависать на 30–40 секунд и более. Разберем по шагам причины такого поведения платформы и детально рассмотрим варианты решения проблемы.

Локализация узкого места через замер производительности

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

Проанализируем выполнение процедур модуля формы и подключенных общих модулей при вызове события ПриСозданииНаСервере. В типовом решении узким местом часто оказывается вызов функции проверки актуальности цен на будущие даты — ЕстьЗначенияЦенПозжеДатыПодбора(). Внутри этой функции платформа выполняет следующий запрос:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    МАКСИМУМ(ЦеныНоменклатурыСрезПоследних.Период) КАК Период
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены В (&ВидыЦен)) КАК ЦеныНоменклатурыСрезПоследних

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

Выясним причину: почему виртуальная таблица СрезПоследних работает медленно

Рассмотрим механизм формирования виртуальной таблицы на уровне СУБД:

  1. Отсутствие даты среза и группировка: Обращение к виртуальной таблице СрезПоследних без указания конкретной даты транслируется платформой 1С во вложенный SQL-запрос с группировкой по всем измерениям регистра (Номенклатура, Характеристика, Упаковка и т.д.). СУБД вынуждена сканировать физическую таблицу регистра, находить максимальный период для каждой возможной комбинации аналитики, формируя полный актуальный срез на текущую дату, и только после этого вычислять внешний МАКСИМУМ(Период).
  2. Специфика оптимизатора PostgreSQL: В отличие от файлового движка или некоторых версий MS SQL Server, оптимизатор PostgreSQL при сложных запросах к виртуальным таблицам 1С строит план с группировкой по хешу (HashAggregate). При большом объеме записей операция превышает лимит оперативной памяти (work_mem) и сбрасывается во временные файлы на диск, что многократно увеличивает время выполнения.
  3. Влияние RLS: Использование конструкции ВЫБРАТЬ РАЗРЕШЕННЫЕ заставляет платформу внедрять условия ограничений прав доступа на уровне записей прямо в подзапросы среза, еще сильнее утяжеляя план выполнения.

Способ 1. Замена запроса к срезу последних на проверку по физической таблице

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

Перепишем запрос к реальной таблице регистра сведений, используя условие существования хотя бы одной подходящей записи (механизм быстрого выхода):


ВЫБРАТЬ ПЕРВЫЕ 1
    1 КАК ПолеОтбора
ИЗ
    РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
    ЦеныНоменклатуры.ВидЦены В (&ВидыЦен)
    И ЦеныНоменклатуры.Период > &ДатаПодбора

Разберем преимущества такой конструкции:

  1. Запрос обращается к реальной физической таблице без дорогостоящих вычислений агрегатных функций и группировок.
  2. Использование ПЕРВЫЕ 1 позволяет СУБД прервать сканирование индексов сразу при обнаружении первой совпавшей строки. Время выполнения сокращается с десятков секунд до сотых долей миллисекунды.
  3. Для максимальной скорости убедимся, что измерение ВидЦены в регистре сведений является либо первым по порядку в метаданных, либо для него включено свойство Индексировать. Это позволит СУБД задействовать прямой поиск по индексу.

Способ 2. Отказ от проверки будущих цен и контроль при проведении

Если в бизнес-процессах предприятия ввод цен будущими датами не используется, можно полностью отключить ресурсоемкую проверку в общем модуле:

  1. В функции ЕстьЗначенияЦенПозжеДатыПодбора() жестко возвращаем значение Ложь без отправки запросов в базу данных. В результате подбор товара строится по быстрому срезу последних без фильтрации по дате.
  2. Чтобы исключить человеческий фактор и ошибки менеджеров, запрещаем установку будущих дат на уровне документа УстановкаЦенНоменклатуры в процедуре ПередЗаписью() или через подписку на событие.

Способ 3. Перевод выполнения в привилегированный режим

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


УстановитьПривилегированныйРежим(Истина);

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	1
    |ИЗ
    |	РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
    |ГДЕ
    |	ЦеныНоменклатуры.ВидЦены В (&ВидыЦен)
    |	И ЦеныНоменклатуры.Период > &ДатаПодбора";

Запрос.УстановитьПараметр("ВидыЦен", ВидыЦен);
Запрос.УстановитьПараметр("ДатаПодбора", ДатаПодбора);

ЕстьЦены = НЕ Запрос.Выполнить().Пустой();

УстановитьПривилегированныйРежим(Ложь);

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

Способ 4. Регламентное обслуживание и настройка СУБД PostgreSQL

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

  1. Сбор актуальной статистики: При неактуальной статистике оптимизатор строит неоптимальные планы (например, выбирает полное сканирование таблицы Seq Scan вместо использования индексов). Запустим сбор статистики через консоль администрирования или утилиту командной строки: vacuumdb --analyze ИмяБазыДанных
  2. Настройка фонового автовакуума: Проверим параметры в конфигурационном файле postgresql.conf. Значения autovacuum_vacuum_scale_factor (рекомендуется 0.05–0.1) и autovacuum_analyze_scale_factor (рекомендуется 0.02–0.05) должны позволять СУБД своевременно обновлять статистику по часто модифицируемым таблицам.
  3. Выделение оперативной памяти: Увеличим параметр work_mem (например, до 32–64 Мб в зависимости от общего объема ОЗУ сервера), чтобы операции сортировки и хеширования не сбрасывались во временные файлы на диск.

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

← На главную