Почему тормозит прокрутка таблицы значений на обычной форме 1С и как это исправить?

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

Разработчики, работающие с обычными формами в «1С:Предприятии 8», нередко сталкиваются с загадочной проблемой: при прокрутке большой таблицы значений интерфейс пользователя начинает сильно зависать («фризить»). Ситуация усугубляется, когда другой пользователь запускает на сервере тяжелую обработку или отчет. При этом замер производительности в конфигураторе показывает, что никакой код на встроенном языке в этот момент не выполняется, а сетевой трафик между клиентом и сервером исчисляется считанными байтами.

В этой статье мы подробно проанализируем причины такого поведения платформы, выясним, почему проблема обостряется при переходе с PostgreSQL на MS SQL Server, и разберем практические шаги по устранению этой архитектурной особенности работы с табличными полями.

В чем причина неявных вызовов сервера?

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

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

Почему проблема обострилась после перехода на MS SQL Server?

Переезд базы данных с PostgreSQL на MS SQL Server часто делает эту проблему критической. Проанализируем, почему это происходит:

  1. Различия в механизмах блокировок (режим RCSI): По умолчанию PostgreSQL работает в режиме многоверсионности (MVCC), где читающие транзакции никогда не блокируются пишущими. В MS SQL Server по умолчанию используется классический механизм блокировок. Если на сервере не включен режим блокировок RCSI (Read Committed Snapshot Isolation), любой тяжелый запрос на запись или чтение данных другими пользователями накладывает блокировки на таблицы СУБД. В результате микро-запросы на получение представлений встают в очередь и ждут освобождения ресурсов.
  2. Параллелизм запросов (MAXDOP): Если в настройках MS SQL Server параметр максимальной степени параллелизма (Max Degree of Parallelism) равен 0 (по умолчанию), СУБД может выделить все доступные ядра процессора под выполнение одного тяжелого аналитического отчета. Простые запросы на получение представлений ссылок зависают в очереди ожидания процессора, что моментально приводит к «замерзанию» интерфейса 1С у скроллящего пользователя.
  3. Конкуренция за оперативную память: MS SQL Server стремится забрать под свой кэш всю доступную память. Если сервер приложений 1С и СУБД находятся на одном физическом сервере, нехватка ОЗУ заставляет операционную систему уводить процессы 1С (rphost) в своп-файл на диске, существенно замедляя обработку любых клиент-серверных вызовов.

---

Пошаговое решение проблемы на уровне кода 1С

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

Рассмотрим по шагам, как переписать алгоритм работы с таблицей значений:

Шаг 1. Добавление строковой колонки в структуру Таблицы Значений

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

Шаг 2. Оптимизация запроса получения данных

В запросе, который собирает аналитику для заполнения таблицы, мы сразу будем получать строковые представления для всех ссылок с помощью конструкции ПРЕДСТАВЛЕНИЕ(). Это позволит выполнить тяжелую операцию получения наименований один раз пакетным запросом.

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


// Создаем структуру таблицы значений на форме
ТаблицаАналитики = Новый ТаблицаЗначений;
ТаблицаАналитики.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТаблицаАналитики.Колонки.Добавить("НоменклатураПредставление", Новый ОписаниеТипов("Строка")); // Новая текстовая колонка
ТаблицаАналитики.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

// Формируем запрос для заполнения данных
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Товары.Номенклатура КАК Номенклатура,
    |	ПРЕДСТАВЛЕНИЕ(Товары.Номенклатура) КАК НоменклатураПредставление,
    |	Товары.Количество КАК Количество
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах КАК Товары";

РезультатЗапроса = Запрос.Выполнить();
ТаблицаАналитики = РезультатЗапроса.Выгрузить();

Шаг 3. Настройка свойств колонки Табличного Поля на форме

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

  1. Откройте свойства табличного поля на форме.
  2. Перейдите в свойства колонки, отображающей номенклатуру (например, «Номенклатура»).
  3. В свойстве Данные (DataPath) укажите имя нашей новой текстовой колонки: НоменклатураПредставление.
  4. Саму колонку Номенклатура (содержащую физическую ссылку) можно сделать скрытой (снять флажок Видимость). Она останется в таблице значений, и вы сможете обращаться к ней в коде при записи изменений обратно в базу данных.

Таким образом, при прокрутке таблицы платформа будет мгновенно отображать обычный текст, хранящийся в локальной оперативной памяти клиента. Обращений к серверу СУБД больше происходить не будет.

---

Оптимизация на уровне настроек СУБД MS SQL Server

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

Рекомендация 1. Включение режима RCSI (Read Committed Snapshot Isolation)

Этот режим позволяет читающим транзакциям получать согласованные данные из хранилища версий строк в базе данных tempdb, полностью исключая блокировки чтения пишущими транзакциями. Для включения выполните в среде MS SQL Server Management Studio (SSMS) следующий скрипт:


ALTER DATABASE [ИмяВашейБазыДанных] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяВашейБазыДанных] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяВашейБазыДанных] SET MULTI_USER;

Рекомендация 2. Настройка параметра MAXDOP

Ограничьте максимальное количество ядер, выделяемых под выполнение одного запроса. Для совместной работы с 1С рекомендуется устанавливать MAXDOP в значение 1 (для старых или слабонагруженных систем) или в диапазоне от 2 до 4 для современных многоядерных серверов. Параметр Cost Threshold for Parallelism рекомендуется поднять со стандартного значения 5 до 50, чтобы СУБД не пыталась распараллеливать простые запросы.

Рекомендация 3. Разделение и ускорение базы TempDB

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

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

← На главную