powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
16 сообщений из 16, страница 1 из 1
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006064
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тут ковыряюсь надо всякими древовидными и прочими графовыми примочками. В частности, имею собственные таблицы метаданных и прав доступа к объектам. Встроенная система прав доступа не совсем устраивает, поскольку кроме имеющегося набора прав доступа необходимо использовать специфические. К примеру, право на просмотр удаленных записей, право на просмотр истории модификации записей или право на блокировку и снятие блокировки учетных регистров на определенных учетных периодах.
А вот имеющаяся система учетных записей и ролей вполне устраивает, и я использую некий гибрид встроенных средств авторизации доступа с собственными примочками. Особенностью такой струткуры является тот факт, что роли и пользователи могут принадлежать (быть дочерними) одновременно нескольким другим ролям. То есть, это НЕ дерево, а направленный граф более сложной структуры (а вот в SQL 6.5 было настоящее дерево). Работать с таким структурами - сплошное удовольствие (есть над чем извилины поразмять). Права доступа делятся на установленные (Set) и вычисляемые (Calc). При изменении какого-либо Set-права на доступ роли к объектам триггер должен перевычислить Calc-права как этой роли, так и всех входящих в нее прямо или косвенно ролей и учетных записей.
Подобные задачи весьма изящно реализуются с помощью рекурсивных триггеров. Сотворил я такой триггер, проверил - работает. НО... При количестве записей в таблице прав всего 100 - 200 модификация прав производится аж 5 секунд!!! Без рекурсии модификация всех записей таблицы, даже многократная отрабатывают практически мгновенно. Включаешь рекурсию - полный тормоз! И это при всем при том, что количество рекурсивных запусков триггера - не превышает 10 (проверено выдачей диагностических сообщений на входе в триггер). Грубо говоря, количество рекурсивных запусков триггера равно максимальному количеству уровней подчинения ролей в графе (а их обычно более 10 и не бывает).
Поскрипел зубами, сделал триггер НЕ рекурсивный, внутри которого на переменной типа Table реализовал тот же самый алгоритм на циклах (псевдорекурсия). Теперь просто летает! Вот и используй после этого рекурсию... В общем-то понятно, что сохранение контекста и создание нового при рекурсивных запусках - вещь довольно ресурсоемкая. Но что до такой степени ресурсоемкая, я, честно говоря, не ожидал. А степень такова, что от наличия рекурсивных триггеров становится ни холодно, ни жарко. Можно просто с успехом забыть об их существовании...
Такие вот дела... Просто эмоции переполняют...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006088
Inna
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А нельзя ли поподробней, как Вы реализовали нерекурсивный алгоритм?
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006102
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В принципе, ранее с SergSuper вскользь этот вопрос обсуждался. При работе рекурсивного алгоритма апдейтятся родительские записи, которые рекурсивно запускают триггер на апдейт дочерних записей, которые в свою очередь... и т.д. Как это сделать НЕ рекурсивно? С помощью двух временных таблиц (или двух переменных типа table). В первую изначально помещаются идентификаторы записей из корня графа (записи, не являющиеся ничьими чайлдами). Потом в обыкновенном цикле While выбираются во вторую таблицу идентификаторы дочерних записей для родительских, которые значатся в таблице1. С ними делается все, что нужно, после чего родительские записи в таблице1 удаляются, а туда копируются идентификаторы записей из таблицы2, сама таблица2 очищается. То есть при подготовке следующего цикла дочерние записи превращаются в родительские.
Можно выкрутиться и на одной таблице, заведя вспомогательное поле (bit), в котором ставится метка, родительская эта запись или дочерняя. Для превращения дочерних записей в родительские достаточно проапдейтить метки.
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006106
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот и трабла вылезла нежданно-негаданно... Ранее обсуждалась уже такая конструкция (обратите внимание на алиас):
update Chld set Chld.SomePermission=1
from GraphTable Parent, GrafTable Chld
where ....
Конструкция работает прекрасно, пока граф является деревом. А вот когда деревянность его улетучивается, начинается свистопляска... Когда у одного чайлда несколько родителей, апдейт проходит, используя значения только одного из них - первого попавшегося . В принципе, на Case-ах агоритм разрешения конфликтов реализован внутри самого апдейта. Но конфликты не возникают! Чертов update однопроходный!
Сижу теперь мудрю, как заставить работать со всеми родителями. Запускать для каждого родителя свой update тоже не хочется - количество выданных update-ов при пересчете прав будет того же порядка, как и количество записей в таблице, а это в плане тормознутости сильно плохо. Перейти на курсоры - тоже приятного мало. Куда ни ткнись, кругом сплошные тормоза...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006109
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извиняюсь - а какое значеие должно использоваться вместо первого попавшегося?
Я в таких случаях обычно записываю во временную таблицу изменения, которые надо сделать, потом группирую их в другую временную таблицу и уже потом меняю основную с помощью последней таблицы.
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006110
cube
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а есть где-то инф. по реализации подобных структур на SQL Server, plz?
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006125
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006130
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Извиняюсь - а какое значеие должно использоваться вместо первого попавшегося?
Да все по очереди. Вкратце дело обстоит так. Сравниваются три величины - Set-право, установленное в чайлде, текущее Calc-право в чайлде и текущее Calc-право в родителе. Если Set-право в чайлде устновлено в некое значение (не Null), то Calc-право в чайлде устанавливается равным ему (установленное явно право для конкретной роли/логина должно выиграть в любом случае). В противном случае если на данном этапе Calc-право чайлда не определено (is Null), то ему присваивается Calc-право родителя. Если же оно определено и одновременно определено Calc-право родителя, причем один из них Deny (0 для поля bit), то Calc-праву чайлда присваивается Deny (при вхождении учетной записи в разные роли, одной из которых назначено право Deny, а другой Grant, Deny должно выигрывать). Вот такой механизм разрешения конфликтов прав доступа, предоставляемых через разные роли, полностью согласующийся с идеологией MS SQL Server 2000.

>Я в таких случаях обычно записываю во временную таблицу изменения, которые надо сделать, потом группирую их в другую временную таблицу и уже потом меняю основную с помощью последней таблицы.
Проблема в том, что во время апдейта некоторые записи должны проапдейтиться по нескольку раз (по числу родительских ролей, в которые они входят). Может, мы говорим о разных вещах? Я твою мысль не уловил, нельзя ли поподробнее. Хочу заакцентировать внимание - на одном апдейте в данной ситуации выкрутиться не получается. А множество апдейтов и/или курсоры иже с ними - это тормоза еще те.
P.S. Вчера у меня была надежда на то, что утро вечера мудренее. К сожалению, никаких новых мыслей не возникло. Похоже, придется вместо движка устанавливать тормоз...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006147
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давай по почте пришли структуру таблицы. Я так и не понял что такое Set-право, Calc-право. Это разные поля или разные значения одного поля? Grant, Deny - это 0 и 1 ?
Мне кажется это всё делается одним упдейтом.

sergsuper@mail.ru
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006162
cube
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>http://mega.km.ru//health/encyclop.asp?TopicNumber=549&search=%C3%E5%EC%EE%F0%F0%EE%E9
заманчиво...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006184
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2SergSuper. Прежде всего, спасибо за предложенную помощь.
Set-право - это то, которое установил администратор конкретно для данной роли (или логина). 0- Deny, 1 - Grant, Null - определяется ролями, в которую входит данная запись.
Calc-право - это вычисленное значение права с учетом вхождения в роли. 0 и 1 аналогичные. Null - еще не подсчитано (на промежуточных стадиях работы алгоритма). После отработки алгоритма обязательно принимает значение 0 или 1 (не Null).
Сергей, спасибо за предложение помочь, но до меня, кажется, дошло, что ты имел в виду. Буду пробовать.
2Cube. Я не сторонник перекладывания собственных задач на плечи отзывчивых энтузиастов (вроде SergSuper). Если ты имел в виду саму задачу, то... ну уж такая попалась. Зато интересно! А представь, что ты не испытываешь ни чувство голода, ни холода, ни в анусе у тебя не свербит... И какой же интерес от такой жизни? Хоть ложись да помирай...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006186
andy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня вот какой вопрос на эту тему созрел.

А вы уверены, что впихивание этой логики в хранимые процедуры (триггеры) дает выигрыщ\ш в производительности?

Я просто занимался сравнением и получается по крайней мере не быстрее. Хотя все зависит от количества записей, использумых на каждой итерации. Если удается это все не забирать из СКУЛ сервер, то оно и так ок.

Просто ИМХО создание временных таблиц тоже не самый хороший выход. Это медленно. Хотя может без них и нельзя...

А то, что вы тут обсуждаете вроде бы как ни что иное как поиск в ширину.
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006194
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А куда еще это логику деть? На клиента, что ли? Так еще медленнее получится. На каждой итерации нужно по сетке туда-сюда таскать результаты и посылать на сервер запросы (предварительно НЕ скомпилированные).
А вот сделать так, чтобы действительно быстродействие устраивало - не получается. Можно сделать либо медленно, либо ОЧЕНЬ медленно. По мне бы хотя бы первое...
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006198
andy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Зачем почему на клиенте? Это смотря на чем писать, если например на АСП, то все равно на сервере, никаких сеток...

А насчет того, как это одним апдейтом сделать, то тут я думаю СуперСерг имел ввиду примерчик с левыми и правыми индексами в дереве (это есть у Celko). СуперСерг вроде бы сам триггер для их вычисления писал. Он позволяет одним запросом получать всех потомков (не только непосредсвенных) нужной ноды. Я вот только не могу сообразить как тебе с сетью то быть.
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32006202
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тот алгоритм годиться только для деревьев. А тут НЕ дерево. С деревом и проблем бы не было тех, из-за которых весь сыр-бор.
...
Рейтинг: 0 / 0
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
    #32007962
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кажется, я понял, откуда возникают тормоза при работе с рекурсивным триггером. Помог ответ alexeyvg, данный на другой ветке: http://www.sql.ru/cgi-bin/UltraBoard/UltraBoard.pl?Action=ShowPost&Board=mssql&Post=1387&Idle=365&Sort=0&Order=Descend&Page=0&Session=
В триггере использовались временные таблицы. Из-за этого триггер компилировался при каждом вызове на каждом шаге рекурсии. Отсюда и тормоза. Я полагаю, что для рекурсивного триггера, рекомпиляция которого не производится при каждом вызове, быстродействие должно быть вполне нормальным. Еще раз большое спасибо alexeyvg.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]