2014-07-10 2 views
0

Я строю небольшую систему разрешений, но, к сожалению, я не эксперт SQL любым способом.MySQL: лучший способ проверить, имеет ли пользователь разрешение по ролям

В этой системе я решил предоставить всем пользователям роль, а затем назначить определенные разрешения для ролей. Мои текущие таблицы базы данных выглядит следующим образом:

enter image description here

Мой вопрос: Какой самый лучший способ проверить, является ли данный User.id в качестве разрешения, указав значение Permission.permission_name. Я придумал следующий запрос:

SELECT EXISTS (

    SELECT perm.id 

    FROM `User` userr 

    INNER JOIN `Role_Permission` connectionc 
    ON userr.role_id = connectionc.role_id 

    INNER JOIN `Permission` perm 
    ON connectionc.permission_id = perm.id 

    WHERE userr.id = 1 
    AND perm.permission_name LIKE 'doStuff' 

) as userHasPermission 

Он работает, но от моего понимания присоединения дорого и что запрос присоединяется содержанием 3 таблицы, а затем фильтровать то, что ему нужно.

Ссылка на sqlfiddle: http://sqlfiddle.com/#!2/6ed7b/1

Спасибо.

+1

Немного сбивает с толку "INNER JOIN роль" роль user_r.id = role.id ". Не должно быть «INNER JOIN« Роль »роль ON userr.role_id = role.id». IMO. Я не вижу причин, по которым нужно присоединяться к «ролям». –

+0

@JA Вы правы. ;) Просто отредактирован. – TCB13

+0

SQL кажется правильным. Не могли бы вы инициировать/предоставить sqlfiddle.com, пожалуйста? –

ответ

2

Я не думаю, что есть много возможностей для оптимизации запроса. Из сценария реального мира, независимо от того, насколько велика таблица пользователя, роль и таблица разрешений не должны превышать 3 цифр, и поэтому role_permission не будет превышать 998001 записей. Если все правильные столбцы проиндексированы правильно, я считаю, что sql будет довольно быстрым (< 0,1 сек). Вы всегда можете проверить EXPLAIN, проверьте, есть ли какие-либо узкие места.

(Не вкл.) В качестве альтернативы, работая над подобным проектом в последнее время, есть несколько вариантов выбора, чтобы улучшить скорость, получаемую от «конечного» нет. записей.

  • Память: Вы можете сохранить все эти соответствующие таблицы/данные в памяти (в отличие от диска), чтобы свести к минимуму ввод/вывод соответствующей задержки.

  • NoSQL: вы можете выбрать решение NoSQL, такое как mongoDB, и/или реализовать noSQL-подобную структуру в MySql для устранения Joins.

  • Redis: Возможно, лучшее решение, если вы хотите думать вне коробки. Самый быстрый из всех.

1

Я не думаю, что есть много возможностей для оптимизации, не нарушая нормализации базы данных. Просто убедитесь, что у вас есть соответствующие индексы.

Некоторые варианты были бы:

  • Магазин имя индекса в таблице разрешений роль, что требует меньше одного соединения. Он не будет нормализован, но это может быть приемлемым, если разрешения редко меняются, и вам действительно нужна максимальная производительность.

  • Не используйте целые идентификаторы для разрешений, вместо этого используйте их имя как уникальный идентификатор. Тогда вам вообще не нужна таблица Permission, если вам не нужно добавлять к ним какой-либо атрибут (но это все равно позволит вам проверить разрешение только с одним соединением).

Вы также должны учитывать, как часто вам нужно выполнять этот запрос.В зависимости от ваших требований может быть приемлемым читать все разрешения пользователя только тогда, когда пользователь входит в систему и сохраняет их на переменных в течение всего сеанса; в этом случае вам не нужна такая высокая производительность для запроса. Или вы можете сначала загрузить не разрешения, а роль, что означало бы меньшее объединение в запросе.

Смежные вопросы