【问题标题】:Best table structure for users with different roles不同角色用户的最佳表结构
【发布时间】:2012-12-01 13:58:17
【问题描述】:

我们正在开发一个网站,其中包含大约 5 个不同的用户角色,每个角色都有不同的属性。在当前版本的数据库模式中,我们有一个 users 表,其中包含所有用户及其所有属性。

问题是我们需要的属性因用户角色而异。所有用户都具有相同的基本属性,例如姓名、电子邮件地址和密码。但最重要的是,每个角色的属性都不同。有些有社交媒体链接,有些有发票地址等。总共可能有多达 60 个列(属性),其中只有一部分由每个用户角色使用。

表格中总共可能有大约 250,000 个用户,其中最大部分(大约 220,000 个)将是单个用户角色(并使用 60 列中的大约 20 个)。其他 30,000 名用户被划分为其他四个规则,并使用其他 40 列的子集。

从数据库作为开发的角度来看,最好的数据库结构是什么?我的想法是有一个基本 users 表,然后用 users_ moderators 之类的表进行扩展,但这可能会导致很多加入的查询。防止这种情况的一种方法是使用 VIEW,但我已经阅读了一些(过时的?)VIEW 可能会损害性能的文章,例如:http://www.mysqlperformanceblog.com/2007/08/12/mysql-view-as-performance-troublemaker/

“完美”的结构是否存在?有什么建议,或者这真的不是一个问题吗?我们应该将所有用户放在一个大表中吗?

【问题讨论】:

    标签: mysql sql database database-design


    【解决方案1】:

    有两种不同的方法可以解决这个问题。一种叫做“单表继承”。这基本上是您要求 cmets 的设计。它非常快,因为没有连接。然而 NULL 会在一定程度上影响吞吐量,因为胖行比瘦行需要更长的时间才能进入内存。

    另一种设计称为“类表继承”。在这个设计中,超类一张表,每个子类一张表。非关键属性进入它们相关的表中。通常,这种设计可以使用一种称为“共享主键”的设计。在共享主键中,子类表的键id是父类表对应行的id的副本。

    在插入时需要做一些工作,但是当您去连接数据时它会为自己付出代价。

    您应该在 SO(它们有自己的标签)或网络上查找所有这三个。您将获得有关设计的更多详细信息,以及每种设计与您的案例的匹配程度。

    【讨论】:

      【解决方案2】:

      在我看来,这种情况下的“完美”结构是党-角色-关系模型。搜索 Len Silverston 关于数据模型的书籍。一开始看起来很复杂,但它提供了很大的灵活性......

      最大的问题是采用完美解决方案的实用性。除了你,没有人能回答这个问题。重构从来都不是一件容易和快速的任务,所以假设你的项目生命周期是 1 年,花 9 个月偿还“技术债务”听起来更像是在浪费时间/精力/等等。

      关于连接的性能,拥有适当的索引通常可以解决潜在的问题。如果没有,您可以随时实现物化视图;即使mysql没有开箱即用的选项,您也可以自己设计并以不同的方式刷新它(例如,使用触发器或定期/按需启动刷新过程)。

      【讨论】:

      • 感谢您的回复。如果我理解您正确应用party-role-relationship 的建议,我们应该只在 users 中放置最少数量的列,然后在其他表中扩展该表(party 关系)?
      • @vvanscherpenseel :是的,理想情况下,用户表只有很少的列,与作为特定角色成员的用户相关的信息存储在其他表中。此外,某些数据仅在特定关系中才有意义,因此识别正确的存储可能有点棘手 - user_role 或关系......
      • 我明白了。这是一个不错的选择,我一定会考虑。
      【解决方案3】:

      table user table roles table permissions table userRole table userPermission table RolesPermissions

      每个角色在角色权限表中都有权限 每个用户都可以拥有没有角色的权限(扩展...)

      所以在 PHP 中,您只需合并用户角色和扩展权限中的用户权限数组... 在您的“acl”类中,您检查您的用户是否有权查看或处理网页或系统进程...

      【讨论】:

      • 感谢您的回答。但我的问题不是关于 ACL 部分,而是关于角色相关属性的存储。
      【解决方案4】:

      我认为您不必担心这里的速度。 因为这只会是一次。即在会话中的用户登录存储 acl 并下次从那里获取它。

      JOIN 还不错。如果您使用 InnoDB 引擎将索引和外键放在正确的位置,那将会非常快。

      我会为用户和角色 ID 使用一张表。第二张表与角色。第三个资源表,一个将所有资源链接在一起 + 启用标志。

      【讨论】:

      • 感谢您的回答。因此,您建议将所有用户放在一个表中,不管 220,000 个用户的 40 列是否为空?
      • 让我们同意 220,000 行不算什么。我同意 40 列是不好的工程。您可以使用 EAV 模型来存储相关的用户数据。我真的不喜欢将每个用户组的数据都放到表格中。
      • 感谢您的建议。 EAV 在这里是一种可能性,尽管它在规模的另一边可能有点过分。对于 60 个属性来说,这可能有点矫枉过正,但我​​肯定会考虑将其作为一种选择。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2016-11-02
      • 1970-01-01
      • 2016-10-24
      • 2012-01-16
      • 2016-11-16
      • 2022-01-13
      相关资源
      最近更新 更多