我正在构建一个小型权限系统,但遗憾的是我无论如何都不是SQL专家。
在这个系统中,我决定给所有用户一个角色,然后为角色分配特定的权限。我当前的数据库表如下所示:
我的问题是:通过提供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
谢谢。
答案 0 :(得分:2)
我认为优化查询的地方不多。从现实世界场景来看,无论用户表有多大,角色和权限表都不应超过3位数,因此,role_permission不会超过998001条记录。如果正确索引所有正确的列,我相信,sql将非常快(<0.1秒)。您可以随时查看EXPLAIN,检查是否存在任何瓶颈。
(非主题) 或者,最近在一个类似的项目上工作过,几乎没有什么选择可以提高“有限”的速度。没有。记录。
内存:您可以选择将所有这些相关的表/数据保存在内存中(而不是磁盘),以最大限度地减少与I / O相关的延迟。
NoSQL:你可以选择像mongoDB这样的NoSQL解决方案和/或在MySql中实现类似noSQL的结构来消除连接。
Redis:可以说,如果你想在盒子外思考,最好的解决方案。最快的。
答案 1 :(得分:1)
我认为没有太多优化空间,而且不会影响数据库的规范化。只需确保您有适当的索引。
一些替代方案是:
将索引名称存储在角色权限表中,因此需要少一个连接。它不会被标准化,但如果权限很少改变并且您确实需要最大性能,这可能是可以接受的。
请勿对整数ID使用权限,而应将其名称用作唯一标识符。然后你根本不需要表Permission
,除非你需要为它们添加一些属性(但这仍然允许你只用一个连接来检查权限)。
您还应该考虑运行此查询的频率。根据您的要求,仅当用户进入系统并在整个会话期间将其存储在变量上时,才可以读取所有用户权限;在这种情况下,您不需要如此高的查询性能。或者你最初可以加载权限而不是角色,这意味着在查询中加入的次数减少了。