Исходя из ваших правил безопасности, acltest_role_acl.allowed
выглядит избыточным - если имеется запись ACL роли, то можно подразумевать allowed == true
.Если, конечно, вам не нужна возможность «отзывать» целые группы, а не только отдельных пользователей.
Кроме того, ваша модель выглядит хорошо, и вам следует сосредоточиться на ее эффективном хранении в базе данных.
В случае, если ваша СУБД поддерживает это, вероятно, будет хорошей идеей хранить ACL в виде кластеризованной таблицы :
- Если вы хотите эффективно ответить на вопрос "которыйЗаписи ACL имеют данную запись ", тогда порядок столбцов PK в кластеризованной таблице должен быть
{record_id, user_id}
для ACL пользователя и {record_id, role_id}
для ACL роли. - Если вы хотите эффективно ответить на вопрос"какие записи ACL имеет данный пользователь или роль ", то порядок столбцов PK должен быть обратным (т. е.
{user_id, record_id}
и {role_id, record_id}
). - Если вы хотите эффективно ответить Оба вопросы, вам понадобится указатель в обоих «направлениях».К сожалению, вторичные индексы являются дорогостоящими в кластеризованных таблицах, поэтому в этом случае вы можете рассмотреть возможность использования таблицы на основе кучи и двух обычных индексов.
Если ваша СУБД поддерживает это, вы можете сжать передний крайиндекс кластеризации (в Oracle он называется таблицей СЖАТЫЙ ИНДЕКС, ОРГАНИЗОВАННЫЙ).Это устранит некоторую избыточность, возникающую из повторяющихся списков ACL (из ваших комментариев: «обычно много людей с одинаковыми разрешениями» и «существует много строк с одинаковыми разрешениями»).
С другой стороны, если вы в первую очередь беспокоитесь о стоимости хранилища (и / или используете СУБД, которая не поддерживает сжатие), но не возражаете против повышенной сложности и потенциального влияния на производительность, вы могли бы рассмотреть что-тонапример:
![enter image description here](https://i.stack.imgur.com/ps2MM.png)
Поскольку многие записи имеют одинаковые списки ACL (согласно вашему комментарию), эта модель позволит избежать большей части повторений.
Например,если N записей имеют одинаковые 5 записей ACL:
- Для старой модели потребуется N * 5 записей ACL строк .
- Для новой модели потребуется только 6 строк+ N поля , что намного дешевле с точки зрения хранения (6 строк = 5 записей ACL + 1 группа, и поле:
acltest_uspaceData.acl_group_id
).
Проблема заключается в: когда вы вставляете новую запись, как выind "соответствующая" группа ACL?Это можно решить примерно так, но это будет не очень эффективно:
SELECT *
FROM acltest_aclGroup
WHERE
NOT EXISTS (
SELECT user_id, allowed
FROM acltest_users_acl
MINUS -- Or EXCEPT, depending on the DBMS.
SELECT user_id, allowed
FROM <user_acl_tmp>
)
AND NOT EXISTS (
SELECT user_id, allowed
FROM <user_acl_tmp>
MINUS
SELECT user_id, allowed
FROM acltest_users_acl
)
AND NOT EXISTS (
SELECT role_id
FROM acltest_role_acl
MINUS
SELECT role_id
FROM <role_acl_tmp>
)
AND NOT EXISTS (
SELECT role_id
FROM <role_acl_tmp>
MINUS
SELECT role_id
FROM acltest_role_acl
)
Сначала вы создаете временную таблицу для ACL пользователей и ролей (<user_acl_tmp>
и <role_acl_tmp>
), затем вставляете ACLзаписи, которые новая запись должна иметь в них, затем выполните вышеупомянутый запрос, который ищет существующие группы ACL для установления равенства с временными ACL.