Мысли про ACL и производительность
Для начала, думаю, стоит привести небольшой экстракт
беседы в ЖЖ касательно ACL.
- /Ку Ме : Вики не построена на древовидной структуре. Для того чтобы одним запросом доставать все id-шники предков, необходимо или сделать транзитивное замыкание, или организовывать дерево по широко известному «магическому» алгоритму обхода дерева.
Страницы статистики генерятся очень долго, потому что надо проверить ACLs к каждой записи. Это одна из причин, по которой они не наследуются на лету.
Ещё одна наследственная проблема — все связи «родитель-ребёнок» и вообще «предок-потомок» существуют только в голове пользователей =). Ключ — супертаг, а не численный идентификатор. Благодаря этому, например, существует страница Page1/Page2/Page3, даже если не создана страница Page1/Page2 и даже если не создана страница Page1.
- /Alex Kulikov : Мне кажется, что именно эту проблему надо изначально решать. Её решение создаст платформу для более гибкой и быстрой системы =)
- /Ку Ме : А почему вам кажется, что это проблема?
- /Alex Kulikov : Ну смотря как посмотреть на задачу, мне кажется, что если бы в СУБД хранилась структура страниц то была бы куда более высокая производительность вики.
Более того, тот же мускул много быстрее выполняет запросы c проекциями по полям типа INT нежели varchar. Решив задачу грамотного хранения отпадёт вопрос наследствия ACL, ровно как и дупликация многие запросов при построении статистики (не уверен, но догадываюсь, что дело обстоит именно так).
Фишку с тегами можно решить создавая пустые промежуточные страницы маркируя их неким флагом, чтобы они не попадали в список «wanted pages».
Дополнения:
- Насколько я понимаю, то на каждый внутренний линк так же просчитывается ACL при генерации страницы. А может, стоит кешировать их в сессии пользователя, дабы не терзать базу постоянны запросами? Стоит ли вообще хранить ACL для страниц, которые получают значения по умолчанию?
- YuliaShabunio Сейчас, так как ACL лежит рядом со страницей, проблем с его вытаскиванием нет. Что бы мы не намудрили с id, проще (и быстрее), чем есть сейчас, не получится.
- YuliaShabunio Мои мысли, что можно сделать, почти не потеряв производительности:
- «Набор прав» – это три строки, описывающие, кто может читать, писать, комментировать что-то. Что-то не указывается, т.о. набор прав может описывать права на любую страницу.
- В таблице ACL хранить «наборы прав». У каждого есть ID и «родительская страница»
- При редактировании ACL «родительской страницы» правится «набор прав», который с ним связан.
- Права на страницу определяются по «набору прав», ID которого указан в свойствах этой страницы. Как правило это будет ссылка на набор, «родитель» которого – страница верхнего уровня иерархии, хотя не обязательно (м.б. набор по умолчанию, например).
- При правке ACL страницы, у которой нет своего набора, можно выборочно создать новый (на основе того, по которому определяются права этой страницы) или сослаться на любой существующий.
- При создании нового набора прав все страницы, лежащие ниже в иерархии, могут быть «прицеплены» к этому набору.
- При создании новой страницы она автоматически цепляется к набору вышележащей страницы, а если таковой нет – к набору по умолчанию.
- Удалить набор прав можно только когда нет ни одной страницы, ссылающейся на него (вариант – при удалении указать, на какой набор перенастроить все зависящие страницы).
- Набор по умолчанию хранится в настройках, в базе на него указывает незначимый ID (вроде -1).
При этом мы имеем довольно мало «наборов», которые можно загрузить и просчитать для конкретного пользователя очень быстро. Права на каждую страницу при этом определяются ID из таблицы страниц, что тоже очень быстро. И нет необходимости перестраивать всю базу страниц (только базу acl), сооружая пресловутое «дерево», которое для других целей не требуется.
- /Ku Me: ага, я тоже думал о том, что достаточно перестроить таблицу ACLs
- /Ку Ме считает, что такого улучшения вполне хватит. Дерево меня пугало больше, это решение простое и интерфейсно наглядное. За исключением одного пункта «удалить набор прав можно тогда когда нет ни одной страницы» и всё, что с этим пунктом связано. Мне кажется, это будет достаточно тяжело объяснить пользователю при удалении страницы Page1, что страницы Page1/Page2 и Page1/Page3 будут теперь ссылаться на какой-то «набор прав», который хранится непонятно где. Я бы предложил копировать наборы в страницы Page1/Page2 & Page1/Page3, а в странице Page1/Page2/Page4 ставить ссылку на Page1/Page2 (соответсвенно в Page1/Page3/Page5 -> на Page1/Page3 соответственно). Это может будет чуть сложнее алгоритм при удалении, но, по моему мнению, объяснить, что ссылается всегда на родительский набор прав — проще, чем вводить какие-то не привязанные к конкретной странице наборы прав.
- YuliaShabunio Это хорошо тем, что можно сделать незаметно от пользователя. И плохо тем, что наборы будут неконтролируемо плодиться. Мы либо вообще не говорим пользоватлю слово «набор» – и тогда удалить его можно только вместе со страницей. Либо говорим (возможно другими терминами) и показываем всю мощь этой штуки.
- YuliaShabunio Похоже, Роман считает, что второй вариант – это бред.
| Роман Иванов | ничего не понимаю =)
но надеюсь, что вы трое договоритесь =) | 16.09.2003 15:21:28 |
| Sad Weasel | жалко... Я так старалась понятно написать... | 16.09.2003 15:21:51 |
| Роман Иванов | давай объясню, чего не понимаю =) | 16.09.2003 15:22:19 |
| Роман Иванов | "ACL лежит рядом со страницей" – это как? оно ж в соседней таблице лежит | 16.09.2003 15:22:33 |
| Роман Иванов | "хранить «наборы прав" – из чего оно состоит? | 16.09.2003 15:22:56 |
| Sad Weasel | >это как? оно ж в соседней таблице лежит
да, но они связаны 1 к 1. Еще сильнее ускорить можено только сложив в ту же страницу, и все. | 16.09.2003 15:23:25 |
| Роман Иванов | Что такое "родительская страница"? | 16.09.2003 15:23:33 |
| Sad Weasel | >из чего оно состоит Сейчас там напишу.
>Что такое "родительская страница"? Там дальше написано – это страница, при редактировании ACL которой правится этот набор. | 16.09.2003 15:24:16 |
| Роман Иванов | это я видел.
не понимаю пока. жду про набор пояснения =) | 16.09.2003 15:26:13 |
| Sad Weasel | «Набор прав» – это три строки, описывающие, кто может читать, писать, комментировать что-то. Что-то не указывается, т.о. набор прав может описывать права на любую страницу. | 16.09.2003 15:26:34 |
| Sad Weasel | "*", "Вася","$" – это пример набора прав. Если родительская страница у него "Кластер", то при редактировании ACL страницы "Кластер" ты сможешь его изменить.
При создании страницы Кластер/ПодСтраница в нее не скопируется эта конструкция, а подставится просто ссылка на нее. | 16.09.2003 15:29:14 |
| Роман Иванов | ничего не понимаю =((((((( | 16.09.2003 15:29:54 |
| Роман Иванов | когда я захожу в правку АКЛ для Кластер/Подстраница, что я там вижу? | 16.09.2003 15:30:16 |
| Sad Weasel | Ты там видишь "Права этой страницы определяются набором прав <Кластер>" (можно ридонли описание)
И кнопки "Создать тут новый набор прав". "Сменить на другой набор прав" Около "Сменить" – список всех наборов в системе, включая набор по умолчанию. | 16.09.2003 15:32:14 |
| Роман Иванов | уй, нет.
такого не будет.
извини, конечно, но это бред =( | 16.09.2003 15:32:42 |
| Kuso | не уверен, что это бред. | 16.09.2003 15:37:15 |
| Роман Иванов | я почти уверен | 16.09.2003 15:38:04 |
| Kuso | только там галочка стоит "Использовать настройки доступа от страницы уровнем выше" и когда ты её отключаешь, то появляются (без перезагрузки страницы, конечно) любимые текстареи аклей. А когда включаешь — пропадают. | 16.09.2003 15:38:20 |
| Kuso | имхо надо более restrictive ограничения просто наложить на идею и порезать сущность "набор прав" | 16.09.2003 15:38:42 |
| Роман Иванов | вот такое чуть лучше.
но САМУЮ МАЛОСТЬ имхо. | 16.09.2003 15:39:01 |
| Kuso | реально наиболее часто используемая фича — это наследование у родителя. я бы даже сказал, это единственно используемая фича этого решения. она нужная. сейчас я это делаю на группах, но когда групп станет 20–30, это будет пиздец. учитывая, что в каждой группе по 2–3 человека и что группы в группы вкладывать нельзя. | 16.09.2003 15:40:15 |
| Роман Иванов | наследования недостаточно.
нужно уметь добавлять к наследуемым наборам некий небольшой пис, ограничивающий или наоборот расширяющий права. | 16.09.2003 15:41:04 |
| Kuso | а вот это уже пиззздец производительности ощутимый. | 16.09.2003 15:41:31 |
| Kuso | (в два раза, т.е.) | 16.09.2003 15:41:35 |
| Роман Иванов | я знаю.
а что делать? | 16.09.2003 15:41:49 |
| Kuso | если мы на него готовы, то делать его. в полный рост, без малейшего страха и упрёка. если не готовы, то делать как предлагает визель. | 16.09.2003 15:42:22 |
| Роман Иванов | как предлагает визель интерфейсно бред.
как предлагаешь ты – ничуть не лучше того как сейчас – просто мы столкнёмся с другими проблемами. Топологически эквивалентными имеющимся, имхо. | 16.09.2003 15:43:14 |
| Роман Иванов | проблемами в использовании, я имею в виду | 16.09.2003 15:43:26 |
| Kuso | тогда решение Макарова лучше, хотя интерфейсно говённей. | 16.09.2003 15:43:52 |
| Роман Иванов | каково решение Макарова в двух словах? | 16.09.2003 15:44:06 |
| Sad Weasel | <нужно уметь добавлять к наследуемым наборам некий небольшой пис, ограничивающий или наоборот расширяющий права.>
Ну и чем тебе плох вариант с созданием нового набора на основе предыдущего? UI пока не трогаем, я про механизм. | 16.09.2003 15:45:14 |
| Роман Иванов | я не понимаю твоего механизма =( | 16.09.2003 15:45:29 |
| Роман Иванов | обновил | 16.09.2003 15:46:59 |
| Sad Weasel | Так. Еще по-подробнее.
Есть три набора прав "совсекретно", "для друзей", "публично". "совсекретно" – "Я,Я,Я" "для друзей" – "Друзья,Я,*" "публично" – "*,*,*"
ок ? | 16.09.2003 15:47:28 |
| Sad Weasel | (Это был пример). | 16.09.2003 15:47:40 |
| Роман Иванов | не ок, я считаю, что такой подход прямо перпендикулярен существующему подходу.
в другом ПО он имеет право на существование, но не в этом.
=( | 16.09.2003 15:48:32 |
| Sad Weasel | тогда не говори, что ты не понимаешь, а говори, что идеологически не согласен. Это типа очень разные вещи. | 16.09.2003 15:49:15 |
| Роман Иванов | нет, я целиком не понимаю. | 16.09.2003 15:49:34 |
| Роман Иванов | а вот этот кусок понял и он мне не нравится =( | 16.09.2003 15:49:43 |
YuliaShabunio Главная фишка моего подхода – это производительность.
YuliaShabunioА сам термин «набор прав» можно вообще никому никогда не показывать. Интерфейс можно не менять вообще. Но это плохо тем, что пользователь не увидит, какие права наследуются, а какие он уже поправил и они больше не будут меняться при правке ACL родителя.
- YuriMakarov Может быть есть смысл явно указывать откуда наследуются права, типа @Page 1? :), тогда таких проблем не будет и дополнительная гибкость появится – можно наследовать не только от родителя ..
- YuliaShabunio Я предлагала вариант с явным указанием, откуда наследовать права. Мне ответили, что это бред. Может и правда бред, хотя лично мне такая идея нравится.
- RomanIvanov: Нет, ты предлагала другое. Ты предлагала «наборы», которых я всё ещё не понимаю. Делать ссылки в аклях – это совсем другое, как мне кажется.
- Назови «набором» права конкретной страницы. И сделай так, чтобы большинство страниц ссылалось, а реально прописанные права были только у некоторых. Получишь точно то же самое, о чем я и говорила.
- AlexKulikov: Я, кстати, проникся идеей, хороший подход.
- YuriMakarov Если речь про вариант @Page, то см. /Yuri Makarov / Права Доступа / Группы
Там есть и пример реализации (работающий), правда для старой версии, сейчас HasAccess переписана и я не знаю будет ли там это работать.
- YuliaShabunio Беда в том, что этот вариант подразумевает рекурсию и будет заметно медленее текущего. А у нас и так есть проблема со скоростью проверки прав доступа.
- AlexKulikov: Мне кажется что тут будет стоять довольно чёткий вопрос юзабилити. Пользователю совсем не надо знать, откуда страница унаследовала права. достаточно просто при редактировании показать тот «набор прав» который задан у родителя. Если пользователь его изменит — то это будет обыкновенный оверрайд.
- YuliaShabunio Ага, все правильно. Проблема начнется, когда он поправить права на корень дерева и будет ждать, что изменятся права на переписанную страницу
YuliaShabunio Если делать из вики «Дерево», то проблема определения, какие ACL менять при правке корня, а какие не трогать, никуда не девается. И ее тоже надо решать.
- AlexKulikov: Вот простой алгоритм: Есть старый набор к корню «А», есть новый набор к корню «Б», далее смотрим всех наследников прав и исправляем тех у кого идентичный с «А» набор прав на набор «Б». Можно пользователю дать отметить флаг Override all child ALCs
- YuliaShabunio Работать оно, конечно, будет. А вот пользователь будет долго думать, почему у всех страниц ACL изменился, а вот у этой – нет. Проблема не в определении «менять-не менять», проблема в том, как сказать об этом пользователю. И она, похоже, вообще не зависит от лежащией в основе наследования технологии.
YuliaShabunio
Я попробовала систематизировать разные подходы к проблеме. И вот что получилось: /Yulia Shabunio / Wacko ACL
Авто Наследствие
Тут пришла идея промежуточного решения для R4 — добавить при изменении ACL флажок «наследовать», судя по структуре БД можно будет изменить все ACL подстраниц одним запросом.
- /Ku Me: это то решение, от которого мы начали свой поход в дебри =) Мне оно пока кажется наиболее.