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

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

В процессе администрирования и разработки в системе «1С:Предприятие» специалисты часто сталкиваются с загадочной на первый взгляд проблемой. В базе данных (например, крупной корпоративной системе класса «БИТ.ФИНАНС» или ERP) работают два пользователя с абсолютно идентичными правами доступа. У них совпадают группы доступа в режиме «1С:Предприятие», назначены одинаковые роли в конфигураторе, и они подчиняются одним и тем же правилам ограничения доступа на уровне записей (RLS). Тем не менее, у одного пользователя система работает быстро, а у второго при открытии той же самой формы динамического списка всё намертво зависает.

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

Техническая суть проблемы: как взаимодействуют RLS и настройки списка

Динамический список в 1С — это мощный инструмент, который считывает данные из базы порциями (обычно по 45 строк), обеспечивая высокую скорость работы интерфейса даже на таблицах с миллионами записей. Однако итоговый SQL-запрос, который платформа отправляет к СУБД, формируется динамически «на лету» и состоит из нескольких пластов:

  1. Базовый запрос: текст запроса, который разработчик прописал в свойствах динамического списка в конфигураторе.
  2. Условия RLS: шаблоны ограничений, которые платформа автоматически дописывает к базовому запросу (в секцию ГДЕ или через левые соединения LEFT JOIN) для всех таблиц, на которые у текущего пользователя наложены ограничения.
  3. Пользовательские настройки: индивидуальные отборы, сортировки, группировки и условное оформление, которые конкретный пользователь сохранил для этой формы.

Когда у одного пользователя всё работает быстро, а у другого — медленно, дело почти всегда в третьем пункте. Индивидуальные настройки пользователя модифицируют итоговый SQL-запрос. В сочетании с тяжелыми условиями RLS это заставляет СУБД строить неоптимальные планы выполнения запросов.

Проанализируем основные факторы, которые приводят к «зависанию» SQL-запроса при наложении пользовательских настроек на RLS:

1. Индивидуальные сортировки по неиндексированным полям

Если пользователь настроил в списке сортировку по колонке, для которой в метаданных не установлен признак «Индексировать» (или по реквизиту связанного справочника через точку), СУБД не может выдать первые 45 строк порционно. Чтобы отсортировать данные, СУБД вынуждена сначала выбрать абсолютно все записи, доступные пользователю с учетом сложных условий RLS, поместить их во временную таблицу СУБД (tempdb), выполнить сортировку всего объема и только потом вернуть первые строки на форму. Это приводит к полному сканированию таблиц (Index Scan или Table Scan) и колоссальной нагрузке на дисковую подсистему сервера.

2. Использование группировок в списке

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

3. Поля «через точку» и условное оформление

Пользователи любят выводить в списки дополнительные реквизиты, например, Договор.Владелец.ОсновнойПроект. Каждое такое разыменование ссылки заставляет платформу добавлять к итоговому SQL-запросу новые соединения LEFT JOIN. Если на эти связанные таблицы также наложены ограничения RLS, сложность итогового запроса растет в геометрической прогрессии, и оптимизатор СУБД просто «сходит с ума», строя неэффективный план выполнения.

4. Залипание плана запроса (Parameter Sniffing)

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

---

Решение проблемы: Шаг 1. Сброс настроек до стандартных

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

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

  1. В правом верхнем углу формы нажать кнопку «Еще».
  2. Выбрать пункт «Установить стандартные настройки».

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


// Программный сброс настроек конкретной формы для пользователя
ИмяПользователя = "Пользователь1";
КлючОбъекта = "Общая/НастройкиФормы/Справочник_ДоговорыКонтрагентов_ФормаСписка";

// Удаляем пользовательские настройки размещения элементов и колонок
ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, "", ИмяПользователя);

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

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

---

Решение проблемы: Шаг 2. Системное устранение причин зависания

Простой сброс настроек — это борьба с симптомами. Рано или поздно пользователь снова настроит удобный для себя отбор или сортировку, и система опять зависнет. Чтобы решить проблему системно, выполним следующие шаги.

1. Включение производительного режима RLS

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

В обычном режиме 1С динамически подставляет сложные подзапросы в каждое обращение к данным. В производительном режиме система предварительно рассчитывает права доступа пользователей и кэширует их в специальных служебных таблицах ключей доступа (например, регистры КлючиДоступаКОбъектам, КлючиДоступаКРегистрам). При открытии списка СУБД выполняет простое и быстрое соединение с таблицей ключей доступа текущего пользователя, что исключает зависание даже при сложных пользовательских сортировках.

2. Ограничение прав пользователей на изменение настроек списка

На высоконагруженных таблицах (например, списки документов «ЗаказКлиента», «РеализацияТоваровУслуг», проводки или записи регистров) имеет смысл жестко ограничить возможности пользователей по кастомизации списков. Рассмотрим, как это сделать в конфигураторе:

  1. Откроем форму, содержащую проблемный ДинамическийСписок.
  2. Выделим элемент формы типа Таблица, связанный с динамическим списком.
  3. В окне свойств найдем группу «Настройка списка».
  4. Установим свойство РазрешитьИзменениеНастройки в значение Ложь.
  5. Если нужно запретить только определенные действия, мы можем детально настроить свойства внутри пункта НастройкаСвойствЭлементовФормы, например, запретить только группировку или только сортировку по неиндексированным полям.

3. Оптимизация текста запроса динамического списка

Проанализируем сам запрос динамического списка в конфигураторе. При разработке запросов для ДС необходимо придерживаться строгих правил:

4. Индексирование полей для сортировки

Если пользователям жизненно необходима сортировка или отбор по определенному реквизиту (например, по реквизиту «Автор» или «Статус»), обязательно зайдем в свойства этого реквизита в конфигураторе и установим свойство Индексировать в значение Индексировать или Индексировать с доп. упорядочиванием. Это позволит СУБД быстро выполнять сортировку без создания тяжелых временных таблиц в tempdb.

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

← На главную