Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Я тут ковыряюсь надо всякими древовидными и прочими графовыми примочками. В частности, имею собственные таблицы метаданных и прав доступа к объектам. Встроенная система прав доступа не совсем устраивает, поскольку кроме имеющегося набора прав доступа необходимо использовать специфические. К примеру, право на просмотр удаленных записей, право на просмотр истории модификации записей или право на блокировку и снятие блокировки учетных регистров на определенных учетных периодах. А вот имеющаяся система учетных записей и ролей вполне устраивает, и я использую некий гибрид встроенных средств авторизации доступа с собственными примочками. Особенностью такой струткуры является тот факт, что роли и пользователи могут принадлежать (быть дочерними) одновременно нескольким другим ролям. То есть, это НЕ дерево, а направленный граф более сложной структуры (а вот в SQL 6.5 было настоящее дерево). Работать с таким структурами - сплошное удовольствие (есть над чем извилины поразмять). Права доступа делятся на установленные (Set) и вычисляемые (Calc). При изменении какого-либо Set-права на доступ роли к объектам триггер должен перевычислить Calc-права как этой роли, так и всех входящих в нее прямо или косвенно ролей и учетных записей. Подобные задачи весьма изящно реализуются с помощью рекурсивных триггеров. Сотворил я такой триггер, проверил - работает. НО... При количестве записей в таблице прав всего 100 - 200 модификация прав производится аж 5 секунд!!! Без рекурсии модификация всех записей таблицы, даже многократная отрабатывают практически мгновенно. Включаешь рекурсию - полный тормоз! И это при всем при том, что количество рекурсивных запусков триггера - не превышает 10 (проверено выдачей диагностических сообщений на входе в триггер). Грубо говоря, количество рекурсивных запусков триггера равно максимальному количеству уровней подчинения ролей в графе (а их обычно более 10 и не бывает). Поскрипел зубами, сделал триггер НЕ рекурсивный, внутри которого на переменной типа Table реализовал тот же самый алгоритм на циклах (псевдорекурсия). Теперь просто летает! Вот и используй после этого рекурсию... В общем-то понятно, что сохранение контекста и создание нового при рекурсивных запусках - вещь довольно ресурсоемкая. Но что до такой степени ресурсоемкая, я, честно говоря, не ожидал. А степень такова, что от наличия рекурсивных триггеров становится ни холодно, ни жарко. Можно просто с успехом забыть об их существовании... Такие вот дела... Просто эмоции переполняют... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 10:24 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
А нельзя ли поподробней, как Вы реализовали нерекурсивный алгоритм? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 15:41 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
В принципе, ранее с SergSuper вскользь этот вопрос обсуждался. При работе рекурсивного алгоритма апдейтятся родительские записи, которые рекурсивно запускают триггер на апдейт дочерних записей, которые в свою очередь... и т.д. Как это сделать НЕ рекурсивно? С помощью двух временных таблиц (или двух переменных типа table). В первую изначально помещаются идентификаторы записей из корня графа (записи, не являющиеся ничьими чайлдами). Потом в обыкновенном цикле While выбираются во вторую таблицу идентификаторы дочерних записей для родительских, которые значатся в таблице1. С ними делается все, что нужно, после чего родительские записи в таблице1 удаляются, а туда копируются идентификаторы записей из таблицы2, сама таблица2 очищается. То есть при подготовке следующего цикла дочерние записи превращаются в родительские. Можно выкрутиться и на одной таблице, заведя вспомогательное поле (bit), в котором ставится метка, родительская эта запись или дочерняя. Для превращения дочерних записей в родительские достаточно проапдейтить метки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 17:06 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
А вот и трабла вылезла нежданно-негаданно... Ранее обсуждалась уже такая конструкция (обратите внимание на алиас): update Chld set Chld.SomePermission=1 from GraphTable Parent, GrafTable Chld where .... Конструкция работает прекрасно, пока граф является деревом. А вот когда деревянность его улетучивается, начинается свистопляска... Когда у одного чайлда несколько родителей, апдейт проходит, используя значения только одного из них - первого попавшегося . В принципе, на Case-ах агоритм разрешения конфликтов реализован внутри самого апдейта. Но конфликты не возникают! Чертов update однопроходный! Сижу теперь мудрю, как заставить работать со всеми родителями. Запускать для каждого родителя свой update тоже не хочется - количество выданных update-ов при пересчете прав будет того же порядка, как и количество записей в таблице, а это в плане тормознутости сильно плохо. Перейти на курсоры - тоже приятного мало. Куда ни ткнись, кругом сплошные тормоза... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 17:33 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Извиняюсь - а какое значеие должно использоваться вместо первого попавшегося? Я в таких случаях обычно записываю во временную таблицу изменения, которые надо сделать, потом группирую их в другую временную таблицу и уже потом меняю основную с помощью последней таблицы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 17:56 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
а есть где-то инф. по реализации подобных структур на SQL Server, plz? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.05.2001, 17:59 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
2 cube Реализация примерно такая: http://mega.km.ru//health/encyclop.asp?TopicNumber=549&search=%C3%E5%EC%EE%F0%F0%EE%E9 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 09:47 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
>Извиняюсь - а какое значеие должно использоваться вместо первого попавшегося? Да все по очереди. Вкратце дело обстоит так. Сравниваются три величины - 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. Вчера у меня была надежда на то, что утро вечера мудренее. К сожалению, никаких новых мыслей не возникло. Похоже, придется вместо движка устанавливать тормоз... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 10:17 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Давай по почте пришли структуру таблицы. Я так и не понял что такое Set-право, Calc-право. Это разные поля или разные значения одного поля? Grant, Deny - это 0 и 1 ? Мне кажется это всё делается одним упдейтом. sergsuper@mail.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 11:39 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
>http://mega.km.ru//health/encyclop.asp?TopicNumber=549&search=%C3%E5%EC%EE%F0%F0%EE%E9 заманчиво... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 12:43 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
2SergSuper. Прежде всего, спасибо за предложенную помощь. Set-право - это то, которое установил администратор конкретно для данной роли (или логина). 0- Deny, 1 - Grant, Null - определяется ролями, в которую входит данная запись. Calc-право - это вычисленное значение права с учетом вхождения в роли. 0 и 1 аналогичные. Null - еще не подсчитано (на промежуточных стадиях работы алгоритма). После отработки алгоритма обязательно принимает значение 0 или 1 (не Null). Сергей, спасибо за предложение помочь, но до меня, кажется, дошло, что ты имел в виду. Буду пробовать. 2Cube. Я не сторонник перекладывания собственных задач на плечи отзывчивых энтузиастов (вроде SergSuper). Если ты имел в виду саму задачу, то... ну уж такая попалась. Зато интересно! А представь, что ты не испытываешь ни чувство голода, ни холода, ни в анусе у тебя не свербит... И какой же интерес от такой жизни? Хоть ложись да помирай... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 14:49 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
У меня вот какой вопрос на эту тему созрел. А вы уверены, что впихивание этой логики в хранимые процедуры (триггеры) дает выигрыщ\ш в производительности? Я просто занимался сравнением и получается по крайней мере не быстрее. Хотя все зависит от количества записей, использумых на каждой итерации. Если удается это все не забирать из СКУЛ сервер, то оно и так ок. Просто ИМХО создание временных таблиц тоже не самый хороший выход. Это медленно. Хотя может без них и нельзя... А то, что вы тут обсуждаете вроде бы как ни что иное как поиск в ширину. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 14:59 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
А куда еще это логику деть? На клиента, что ли? Так еще медленнее получится. На каждой итерации нужно по сетке туда-сюда таскать результаты и посылать на сервер запросы (предварительно НЕ скомпилированные). А вот сделать так, чтобы действительно быстродействие устраивало - не получается. Можно сделать либо медленно, либо ОЧЕНЬ медленно. По мне бы хотя бы первое... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 16:26 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Зачем почему на клиенте? Это смотря на чем писать, если например на АСП, то все равно на сервере, никаких сеток... А насчет того, как это одним апдейтом сделать, то тут я думаю СуперСерг имел ввиду примерчик с левыми и правыми индексами в дереве (это есть у Celko). СуперСерг вроде бы сам триггер для их вычисления писал. Он позволяет одним запросом получать всех потомков (не только непосредсвенных) нужной ноды. Я вот только не могу сообразить как тебе с сетью то быть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 16:41 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Тот алгоритм годиться только для деревьев. А тут НЕ дерево. С деревом и проблем бы не было тех, из-за которых весь сыр-бор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.05.2001, 17:24 |
|
||
|
Рекурсивные триггеры - не просто тормоз, а полный стоп-кран!
|
|||
|---|---|---|---|
|
#18+
Кажется, я понял, откуда возникают тормоза при работе с рекурсивным триггером. Помог ответ 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.06.2001, 15:48 |
|
||
|
|

start [/forum/topic.php?desktop=1&fid=46&tid=1826420]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
25ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 211ms |
| total: | 317ms |

| 0 / 0 |
