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

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

Каждый администратор и разработчик 1С рано или поздно сталкивается с загадочными проблемами производительности, которые проявляются крайне избирательно. Представьте ситуацию: база данных «1С:Управление производственным предприятием» (УПП), пользователь открывает карточку контрагента, переходит на вкладку «События», и система «зависает» на 10, 20 или даже 30 секунд. При этом у соседнего коллеги с точно такими же правами доступа и на том же терминальном сервере эта вкладка открывается мгновенно.

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

Почему стандартный замер производительности «молчит»?

Первое, что делает разработчик при возникновении лагов — запускает Замер производительности в конфигураторе. Однако в нашем случае замер может показать ошеломляюще быструю работу — например, 0,000129с на самую долгую операцию. Выясним причину, почему так происходит. Выделим два главных фактора:

  1. Отсутствие серверной отладки. Если конфигурация работает в клиент-серверном режиме, а на сервере приложений 1С не включен ключ отладки -debug, все вызовы и операции, выполняемые на стороне сервера, просто не попадут в замер производительности на клиенте. Клиентская часть отрабатывает моментально, а вся задержка происходит на стороне СУБД или сервера приложений.
  2. Особенности работы динамических списков. Вкладка «События» в большинстве типовых конфигураций построена на базе динамического списка. Особенность этого механизма в том, что платформа запрашивает данные из базы не все сразу, а порциями (обычно по 20–45 строк) по мере прокрутки списка пользователем. Сам запрос к СУБД и получение порции данных происходят в фоновом режиме платформы, который встроенный замер производительности 1С напрямую не регистрирует.

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

Настройка Технологического журнала для поиска медленных запросов

Рассмотрим, как локализовать проблему с помощью ТЖ. Если у нас есть возможность развернуть файловую копию базы данных, где воспроизводится баг под конкретным пользователем, мы можем настроить сбор логов локально. Это позволит избежать лишней нагрузки на рабочий сервер.

Разберем по шагам процесс настройки ТЖ для файловой базы данных:

Шаг 1. В каталоге шаблонов настроек (обычно это C:\Program Files\1cv8\conf или индивидуальная папка пользователя) создадим текстовый файл с именем logcfg.xml.

Шаг 2. Запишем в него конфигурацию для отслеживания событий работы с файловой СУБД (событие DBV8DBEng). Если бы мы исследовали клиент-серверный вариант на MS SQL, мы бы отслеживали событие dbmssql. Нам также необходимо собирать подробные свойства запросов, поэтому укажем вывод всех свойств.

Посмотрим на пример файла конфигурации ТЖ:


<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
    <log location="C:\log\log1c" history="1">
        <event>
            <eq property="Name" value="DBV8DBEng"/>
        </event>
        <property name="all"/>
    </log>
</config>

Шаг 3. Запустим 1С под проблемным пользователем, перейдем на вкладку «События», дождемся окончания зависания и закроем программу. В каталоге C:\log\log1c сформируется лог-файл.

Проанализируем полученные данные. В логах мы увидим примерно следующую картину:


56:50.314001-38732001,DBV8DBEng,...,Sdbl='SELECT ALLOWED TOP 20 R.Date_Time A1, ...'

Число 38732001 после дефиса показывает длительность выполнения операции в микросекундах. Это означает, что запрос выполнялся целых 38,7 секунды! При этом у другого пользователя аналогичный запрос на получение тех же самых данных занимает всего 2828000 микросекунд (около 2,8 секунды). Физический запрос в базу данных один и тот же, но время выполнения различается более чем в 13 раз.

Истинная причина: как настройки пользователя ломают работу СУБД

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

Рассмотрим подробнее механизмы СУБД, которые приводят к деградации производительности:

1. Сортировка по неиндексированному полю. По умолчанию динамический список выбирает записи, используя индекс по умолчанию (например, по дате документа). СУБД легко считывает первые 20 записей по индексу. Но если проблемный пользователь случайно или намеренно кликнул по шапке колонки, которая не имеет индекса в СУБД (например, текстовый реквизит «Суть события» или реквизит, получаемый через точку от другого объекта — Ответственный.Подразделение), СУБД больше не может читать данные порциями. Чтобы показать первые 20 строк с такой сортировкой, SQL-сервер выполняет полный перебор (Full Table Scan) всей многомиллионной таблицы событий, сортирует их во временной памяти (TempDB) и только потом отдает результат. Это вызывает колоссальный лаг.

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

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

Разберем по шагам способы решения проблемы

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

Способ 1. Сброс настроек силами самого пользователя

Это самый быстрый и безболезненный способ, не требующий прав администратора:

  1. Откройте форму списка, которая вызывает зависание.
  2. Если форма все-таки открывается через некоторое время, нажмите кнопку «Еще» (или «Действия» в обычном интерфейсе) в верхней панели динамического списка.
  3. Выберите команду «Установить стандартные настройки».

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

Способ 2. Административная очистка настроек конкретного пользователя

Если форма зависает «намертво» и зайти в меню настроек списка под учетной записью пользователя невозможно, администратор может сбросить настройки удаленно:

  1. Зайдите в базу данных под учетной записью с административными правами.
  2. Перейдите в раздел Администрирование -> Настройки пользователей и прав (для управляемого интерфейса) или откройте справочник пользователей в обычном интерфейсе.
  3. Найдите пункт «Очистка настроек» (или «Настройки пользователей»).
  4. Выберите проблемного пользователя и найдите в списке настроек форму контрагента или форму списка событий.
  5. Нажмите кнопку «Очистить».

Способ 3. Программный сброс настроек динамического списка

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


Процедура ОчиститьНастройкиПользователя()
    
    ИмяПользователя = "ИвановИИ"; // Укажите имя проблемного пользователя
    КлючОбъекта = "Справочник.Контрагенты.Форма.ФормаЭлемента.СписокСобытий"; // Пример ключа настроек
    
    // Удаляем настройки из системного хранилища настроек динамических списков
    ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, "", ИмяПользователя);
    
    Сообщить("Настройки динамического списка для пользователя " + ИмяПользователя + " успешно сброшены!");
    
КонецПроцедуры

Способ 4. Превентивная оптимизация динамического списка в конфигураторе

Рассмотрим подробнее, как разработчик может предотвратить подобные проблемы на уровне проектирования системы:

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

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

← На главную