Эксперимент заранее не готовился. Ко мне обратились пользователи с вопросом медленной работы (порой зависания) списка справочника «Партнеры». Запустил под собой, проверил — все нормально, никаких зависаний нет. Запустил (на той же машине) под пользователем, который ко мне обратился — действительно список тормозит, причем только при прокрутке стрелками с клавиатуры, но не мышкой. Быстро понял в чем дело — в ПриАктивизацииСтроки происходит получение дополнительной информации по партнеру. Что может быть причиной? Смотрю права — у пользователя назначено более сотни ролей, у меня две (Полные права, Администратор системы). Добавляю пользователю роль «Полные права», проблема остается — список торомозит. Убираю у пользователя все кроме полных прав — проблема торможения списка уходит.
Вывод — большое количество ролей замедляет работу пользователя, что в общем то предсказуемо, но в данном случае подтверждено экспериментально.
Привожу результаты замеров производительности (приведены строки кода и время их выполнения для описываемых выше случаев):
Если НЕ ЗначениеЗаполнено(Партнер) ИЛИ Партнер.ЭтоГруппа Тогда
0,0149994897959184 — «много» ролей
0,0028094977973568 — «мало» ролей
Время выполнения различается на порядок!
Результат = Запрос.Выполнить();
0,0136426805555556 — «много» ролей
0,0107065418502203 — «мало» ролей
Контакты = ***КлиентСервер.ПолучитьДопИнфПоПартнеру(Элементы.Список.ТекущаяСтрока);
0,0107463741496599 — «много» ролей
0,0096472290748899 — «мало» ролей
Из замеров видно, что существенные различия во времени исполнения дает строка кода:
Если НЕ ЗначениеЗаполнено(Партнер) ИЛИ Партнер.ЭтоГруппа Тогда
Разбив строку условия на 2 отдельных условия и замерив время, выяснилось, что критичной является часть условия «Партнер.ЭтоГруппа», что логично, так как здесь происходит обращение к БД. Влияния количества ролей на время выполнения другой части условия — НЕ ЗначениеЗаполнено(Партнер), не выявлено.
На этом эксперимент не закончился. Я решил исследовать характер обнаруженной зависимости.
Далее я вернул пользователю исходные роли, добавил роль «Полные права» и стал последовательно удалять по 20 ролей (роли удалялись подряд по списку, роль «Полные права» не удалялась), делая замеры по строке с наибольшей разницей во времени выполнения на каждом из этапов. Результаты представлены ниже.
Строка кода, по которой проводились замеры:
Если НЕ ЗначениеЗаполнено(Партнер) ИЛИ Партнер.ЭтоГруппа Тогда
Результаты замеров представлены на графике:
Из графика видно, что, с учетом неизбежных погрешностей измерений, зависимость линейная.
Выявив характер зависимости, нужно было устранить влияние данного кода на работу списка.
Для этого код был выделен в отдельную процедуру, а в «ПриАктивацииСтроки» вместо него добавлен вызов обработчика ожидания:
В
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ПодключитьОбработчикОжидания("ВывестиДопИнфоПоПартнеру",0.2,Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВывестиДопИнфоПоПартнеру()
Контакты = ***КлиентСервер.ПолучитьДопИнфПоПартнеру(Элементы.Список.ТекущаяСтрока);
КонецПроцедуры
Таким образом влияние времени выполнения данного кода на скорость прокрутки списка было исключено.
Это решение подсказано в комментариях к начальной версии данной публикации участником nixel , за что ему огромное спасибо.
Данная публикация является логическим продолжением другой моей публикации, связанной со скоростью работы списков —
УТ 11: Ускоряем форму подбора номенклатуры , в которой предлагается решение вопроса ускорения работы списка путем изменения его запроса. Но, как выясняется, проблема может лежать и в совершенно другой плоскости.
Спасибо всем, кто высказал дельные замечания в комментариях, что позволило дополнить публикацию.
P.S.
07.02.2024
В описании изменений релиза 8.3.7.1845 платформы от 30.12.15, в разделе «Оптимизация» есть информация о том, что имевшая место существенная зависимость времени выполнения запросов от количества ролей назначенных пользователю была устранена. В частности говорится, что запросы для пользователей с неполными правами выполнялись недостаточно быстро — время выполнения запроса существенно зависело от количества ролей, назначенных пользователю. В результате было оптимизировано выполнение запросов для пользователей с неполными правами, с использованием ограничений доступа к данным, при большом количестве ролей и теперь время выполнения запроса не имеет существенной зависимости от количества ролей, назначенных пользователю.
Технологическая платформа 8.3. Версия 8.3.7.1845. Список изменений и порядок обновления
Интересно, как поведет себя замер, если конструкцию «НЕ ЗначениеЗаполнено(Партнер)» заменить на «Партнер <> Справочники.Партнеры.ПустаяСсылка()» ? Может в данном конкретном случае такое влияние оказывает именно проверка на заполненность? Ведь не зря же в типовых конфигурациях пишут функцию проверки заполненности именно сравнением с пустым значением типа… Вот — нашел на скорую руку:
Показать
Лишнее подтверждение тому, что разработчики типового решения озабочены чем угодно, но только не производительностью работы системы, и не проводят тестирование должным образом.
На УПП 1.3, при гораздо меньшем количестве ролей (не сотни, а «всего» десятки), тоже заметно замедление работы, если у пользователя много ролей. А в типовых ролях УПП и не получается дать пользователю одну-две роли.
(2) kapustinag, разработчики типовых решений озабочены оменно типизацией своего решения. а для ускорения работы есть другие специалисты ))) чем бы вы зарабатывали, если бы типовые решения были идеальными?
а RLS включено или нет?
(4) headMade, RLS не используется, включение / выключение настройки в «Ограничивать доступ на уровне записей» в БД на результат теста не влияет — проверил.
(1) w-divin, Торможение вызывает Партнер.ЭтоГруппа — разбил условие на 2 и проверил, вот что получилось:
ОбщийМодуль.***КлиентСервер.Модуль 1 561 Если Партнер.ЭтоГруппа Тогда 144 2,988937 23,43,
то есть 2,988937 / 144 = 0,0207565069444444
а строкой ЗначениеЗаполнено(Партнер) вообще можно пренебречь:
ОбщийМодуль.***КлиентСервер.Модуль 1 558 Если НЕ ЗначениеЗаполнено(Партнер) Тогда 144 0,000680 0,01
то есть 0,000680 / 144 = 4,722222222222222e-6 🙂
(6) Tsaregorodtsev, мне к сожелению негде проверить влияние большого количества ролей — у меня их всего 18, но могу предложить заменить проблемный участок кода на:
Показать
(7) w-divin, спасибо. Думаю общей рекомендацией в условиях большого количества ролей будет отказ от объектной модели доступа к данным в пользу табличной (запросы).
Мы у себя вообще решили отказаться от типового механизма ролей УТ 11 и формируем новый набор полноценных ролей как именно ролей, а не непонятно чего. И здесь вопрос производительности на самом деле вторичен, но как дополнительный фактор тоже учитывался при принятии решения о смене концепции работы с правами.
Ладно, ключевую функцию мы нашли: тормозит ЭтоГруппа().
Встают вопросы:
1) Как выполняется функция и где возникают тормоза: на 1С или на СУБД?
2) При чем тут роли?
3)
Работа RLS проверяется не включением-выключением, а просмотром текста запроса уровня СУБД в трассировке.
Ответы на эти вопросы можно получить сравнением трассировок (события batch complete, rpc complete, showplan xml) для случая с одной ролью и множеством ролей. Если трассировки идентичны — вопрос к разработчикам платформы. Иначе — причина будет видна из трассировок.
На самом деле виноваты именно RLS, т.к. проверка, а следует ли использовать RLS, производится, грубо говоря, внутри RLS-запроса. Учите матчасть.
(9)asved.ru,
Ответы на эти вопросы можно получить сравнением трассировок (события batch complete, rpc complete, showplan xml) для случая с одной ролью и множеством ролей. Если трассировки идентичны — вопрос к разработчикам платформы. Иначе — причина будет видна из трассировок.
На самом деле виноваты именно RLS, т.к. проверка, а следует ли использовать RLS, производится, грубо говоря, внутри RLS-запроса. Учите матчасть.
Ну и что ты будешь делать после изучения запроса уровня СУБД? Свою платформу писать сядешь?
Изучи вопрос и напиши что у тебя получилось.
(10) Tsaregorodtsev, т.е. Вы желаете, чтобы я разобрался в Вашей проблеме и сформировал решение? Такие вещи, как правило, оплачиваются, и недешево.
Куда копать, если желаете разобраться в сути проблемы, я Вам подсказал. Остальное — Ваше дело.
Интересно, а включение привелегированного режима влияет на скорость?
Я считаю что и роли и rls играют роль в скорости работы, но начинать заморачиваться надо только если данных реально много, все крутится на сервере 1с, sql сервер отдельно работает и сжатие базы, переиндексация, обновление статистики, наконец дефрагментация винта, ускорение в виде 10го рейда или 1го рейда из ssd винтов, не помогает.
От rls можно отказаться только если от вас не требуют чтобы все начальники отделов видели только продажи/контрагентов своего отдела, а менеджеры вообще только свои продажи/своих контрагентов. Все кто хает RLS предлагайте быструю реализацию данной задачи.
p/s Продажи в смысле не только документы РеализацияТоваровУслуг, а все данные базы видны только по списку разрешенных контрагентов, организаций, складов.
(9) хорошее замечание. возможно имеет смысл вычистить все запросы из рлс и тормозов станет меньше?
(13) rar_xxx, как-нибудь посмотрите в план запроса со сложным RLS — если сумеете не материться — Вы очень сдержанный человек.
Речь не о том, что RLS — плохо, речь о том, что не следует делать чрезмерно сложные RLS, т.к. это усложняет запрос и снижает устойчивость плана запроса, как следствие мы получаем падение и нестабильность производительности.
(14) eeeio, проще создать новые агрегированные роли вообще без RLS, как указано в (8)
ОФФ. Как теперь подписаться на ответы, не создав новое сообщение?
Подскажите кто-нибудь.
(12) asved.ru, Я возможно неправильно Вас понял, возможно Вы имели ввиду, что производительность снижается не столько из за большого количества ролей как такового, сколько из за факта наличия шаблонов ограничений в выбранных у пользователя типовых ролях УТ11 — мы ведь о ней сейчас говорим. Это на самом деле несложно проверить и без погружения в такие дебри, как анализ запросов на SQL сервере. Постараюсь это проделать и сообщу о результатах.
(12) asved.ru, Результаты замеров с учетом наличия в ролях пользователя роли с шаблоном ограничений RLS (само разграничение как я уже говорил в базе отключено):
Строка анализируемого кода:
Если НЕ ЗначениеЗаполнено(Партнер) ИЛИ Партнер.ЭтоГруппа Тогда
Результаты замеров:
Много ролей (> 100, в т.ч. с шаблонами RLS и без): 0,0210996291666667
Мало ролей (2 роли), все без без РЛС: 0,0036270839328537
Мало ролей плюс одна роль с шаблоном ограничений RLS (всего 3 роли): 0,0029737675070028
То есть, само наличие шаблона ограничений RLS в роли никакого влияния на быстродействие не оказывает …
(19) Tsaregorodtsev, а Вы уверены, что в одной из ролей с RLS нет шаблона, по которому платформа, к примеру, строит запрос, сваливающийся в table scan вследствие отсутствия подходящего индекса или банальной ошибки разработчика, или в nested loops? Вы думаете, разработкой типовых конфигураций исключительно ЭТВ занимаются?
И даже если бы это было так — Всего ж не рассчитаешь! ©Падал прошлогодний снег
Повторяю: смотрите план запроса. Сопоставив таблицы БД, на которых выполняются проблемные операции, с метаданными, Вы определите примерный вид RLS-ограничения. А потом ищите его в шаблонах.
Если у нас просто слишком много RLS, и запрос проседает на соединениях с подзапросами, это тоже видно по плану запроса.
Вообще на тему анализа проблем производительности на днях книжка вышла:http://v8.1c.ru/metod/books/book.jsp?id=452
Сам еще не читал, но одобряю.
PS если уж вам так неймется исследовать проблему по методологии «черного ящика» — забацайте 100 ролей без RLS. Поступок будет героический, я про него падаванам рассказывать буду.
Универсальность программного решения всегда приводит к усложнению и снижению быстродействия.
В принципе, что вам мешает создать одну роль для каждой должности, в которую слить все необходимые права?
И к тому же более правильная информация по быстродействию будет в том случае, если вы соберете детальную статистику работы в течении ходя бы полного рабочего дня. Например, соберете показания по APDEX. Ведь на временные показатели, что вы здесь привели, могло повлиять что угодно (например фоновое задание, или формирование проводок другим пользователем, сетевая нагрузка и пр.).
(22) Ворчун, Свой подход к решению обозначенной в публикации проблемы типовой УТ 11 я описал в (8), там как раз про одну роль для каждой должности. Цифры, что я здесь привел повторяются довольно стабильно, условия эксперимента описаны — выводы для себя делайте сами. Про сетевую нагрузку и пр. — спасибо, буду знать.
(21) asved.ru, Ваша склонность залезть поглубже в SQL (похоже по любому поводу) напомнила мне один хороший анекдот:
На улице недалеко друг от друга подрабатывают два гитариста — молодой и старый. Молодой музыкант показывает суперскоростную технику, «пилит» по всему грифу, сногсшибательно импровизирует, а старый скромно стоит в сторонке и извлекает вдумчиво пару-другую нот. Около молодого гитариста — никого, около старого — толпа народу. Один слушатель не выдержал, подошел к старому музыканту и спрашивает: «Как так получается, что тот молодой музыкант быстро играет, показывает фантастическую технику, и его никто не слушает, а вы спокойно играете несколько нот и вас слушает толпа народу?» Старый музыкант подумал и ответил: «Он только еще ищет свою ноту, а я уже нашел…»
(24) Tsaregorodtsev, моя склонность залезть в SQL обоснована тем, что, как правило, большая часть проблем производительности 1С обусловлена проблемами производительности на уровне СУБД. А анализировать проблему нужно там, где она возникает.
(25) asved.ru, за книжку спасибо. А технологический журнал? Зачем же сразу в SQL?
(26) Tsaregorodtsev, директива sqlplan сильно снижает производительность. Причем на DB2 и Oracle — до уровня известного пушного зверька.
Кроме того, графический план просто удобнее смотреть.
Может просто стоит чуть-чуть дописать обработчик события ПриАктивизацииСтроки?
Если в этом обработчике есть как-то тяжелый код, то обычно этот код оборачивается в соседнюю процедуру, подключаемую как обработчик ожидания с задержкой, например, в секунду. Тогда при скроллинге списка с клавиатуры этот тяжелый код не успевает выполняться, так как постоянно срабатывает переподключение обработчика ожидания, а не заложенный в нем код. Если потребуется пример, могу предоставить, а так, думаю, сами разберетесь.
(28) nixel, идея понятна, спасибо!
Было бы достаточно странно, если бы RLS не снижала производительность, с учетом, что каждое условие — это дополнительный подзапрос к основному запросу. Смысла в статье такого рода не вижу. Автор мог бы подробно описать закономерность и принципы работы RLS, вместо того, чтобы писать кучу букв, содержащих только: RLS — отстой.
(30) ojiojiowka, По моему в Вашем комментарии немного смещены акценты относительно изложенного в публикации. Во первых — публикация не посвящена RLS, в ней про это нет ни слова.
Во вторых, публикация посвящена выявлению влияния количества ролей, назначенных пользователю, на производительность его работы. Среди множества ролей, назначенных тестовому пользователю (типовые роли УТ 11, здесь все прозрачно) изначально есть роли с шаблонами RLS (говорим о шаблонах, так как использование RLS в базе отключено), но далеко не все и более того, их «меньшинство». А вот линейный характер выявленной зависимости как раз опровергает утверждение (оно было высказано в комментариях) об определяющем значении в снижении производительности именно наличия в ролях шаблонов RLS. То есть, Ваш тезис, что статья это «наезд» на RLS — неверный. Скорей даже наоборот — влияния наличия в ролях шаблонов RLS на производительность не выявлено (!!!), но суть не в этом.
Мы очень остро столкнулись с проблемой количества ролей на работе встроенной функции «ИзменитьРеквизиты» на какой версии платформы это происходило не скажу (года 1,5 назад), но из-за этой проблемы пришлось написать обработку распарсивающую набор ролей профиля и выдающую одну сводную роль. Правда потом 1С поправили эту проблему, но от сводных ролей мы так пока не отказались)
Ну и хочу на всякий случай напомнить, что в случае с наличием РЛС главное контролировать чтобы на один и тот же объект не было задано прав с разных ролей, если шаблоны в этих ролях одинаковы, то задублируются условия РЛС, что крайне негативно (не линейно) может сказаться на длительности запросов. Такие случаи встречаются и на типовых конфигурациях.