MySQL:检查用户是否具有角色权限的最佳方法

时间:2014-07-10 17:55:55

标签: mysql sql query-optimization inner-join

我正在构建一个小型权限系统,但遗憾的是我无论如何都不是SQL专家。

在这个系统中,我决定给所有用户一个角色,然后为角色分配特定的权限。我当前的数据库表如下所示:

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

谢谢。

2 个答案:

答案 0 :(得分:2)

我认为优化查询的地方不多。从现实世界场景来看,无论用户表有多大,角色和权限表都不应超过3位数,因此,role_permission不会超过998001条记录。如果正确索引所有正确的列,我相信,sql将非常快(<0.1秒)。您可以随时查看EXPLAIN,检查是否存在任何瓶颈。

(非主题) 或者,最近在一个类似的项目上工作过,几乎没有什么选择可以提高“有限”的速度。没有。记录。

  • 内存:您可以选择将所有这些相关的表/数据保存在内存中(而不是磁盘),以最大限度地减少与I / O相关的延迟。

  • NoSQL:你可以选择像mongoDB这样的NoSQL解决方案和/或在MySql中实现类似noSQL的结构来消除连接。

  • Redis:可以说,如果你想在盒子外思考,最好的解决方案。最快的。

答案 1 :(得分:1)

我认为没有太多优化空间,而且不会影响数据库的规范化。只需确保您有适当的索引。

一些替代方案是:

  • 将索引名称存储在角色权限表中,因此需要少一个连接。它不会被标准化,但如果权限很少改变并且您确实需要最大性能,这可能是可以接受的。

  • 请勿对整数ID使用权限,而应将其名称用作唯一标识符。然后你根本不需要表Permission,除非你需要为它们添加一些属性(但这仍然允许你只用一个连接来检查权限)。

    < / LI>

您还应该考虑运行此查询的频率。根据您的要求,仅当用户进入系统并在整个会话期间将其存储在变量上时,才可以读取所有用户权限;在这种情况下,您不需要如此高的查询性能。或者你最初可以加载权限而不是角色,这意味着在查询中加入的次数减少了。