Postgres:多对多列与多列对阵列

NTS*_*NTS 7 postgresql ruby-on-rails

我需要帮助在Postgres数据库中设计复杂的用户权限.在我的Rails应用程序中,每个用户都可以访问一组独特的功能.换句话说,没有预定义的"角色"来确定用户可以访问哪些功能.

在几乎每个控制器/视图中,应用程序都会检查当前用户是否可以访问不同的功能.理想情况下,该应用程序将提供约100种不同的功能,并将支持500k +用户.

目前,我正在考虑三种不同的选择(但欢迎替代品!),并想知道哪种选择提供最佳性能.提前感谢您的任何帮助/建议.

选项1:多对多关系

通过在User表和Feature表之间构建多对多关系,应用程序可以通过查询连接表来检查用户是否可以访问给定功能.

例如,如果连接表中有连接user1feature1的记录,则user1可以访问feature1.

选项2:多列

该应用程序可以将每个功能表示为User表上的布尔列.这样可以避免查询多个表来检查权限.

例如,如果user1.has_feature1为true,则user1可以访问feature1.

选项3:数组列

该应用程序可以将功能存储为User表格中(GIN索引?)数组列中的字符串.然后,要检查用户是否可以访问某个功能,它将在数组列中搜索给定功能.

例如,如果user1.features.include? 'feature1'为true,则user1可以访问feature1.

max*_*max 7

多对多关系是这里唯一可行的选择。他们将其称为关系数据库是有原因的。

为什么?

  • 加入实际上并不那么昂贵。
  • 多列-表中的列数将是可笑的,这将是真正的开发人员地狱。由于每个功能都增加了迁移,因此代码库中的客户流失数量将非常可观。
  • 数组列-使用数组列似乎是一种有吸引力的选择,直到您意识到它实际上只是对将内容填充到逗号分隔的字符串中的一个小改进。您没有引用完整性,也没有代码组织可以从拥有表示应用程序中实体的模型中受益。
    哦,每当要取消某个功能时,您都必须更新这500k +用户中的每一个。VS仅使用CASCADE。

class Feature
  has_many :user_features
  has_many :users, through: :user_features
end

class UserFeature
  belongs_to :user
  belongs_to :feature
end

class User
  has_many :user_features
  has_many :features, through: :user_features

  def has_feature?(name)
    features.exist?(name: name)
  end
end
Run Code Online (Sandbox Code Playgroud)