【问题标题】:what is a better way than arrays overlap? (postgresql)有什么比数组重叠更好的方法? (postgresql)
【发布时间】:2014-06-03 03:59:44
【问题描述】:

我正在为一家商业公司构建一个应用程序,他们需要控制谁可以按项目和角色查看哪些报告,该报告可以属于一个项目,并且可以由多个角色(员工角色)查看。
因此,当提交报告时,它会被标记为项目和角色,例如 "project1" 和 {"manager","seller"} ,例如,从事 project1 工作并且是经理的员工可以看到此报告。 我现在的做法很大程度上取决于数组,这就是我所拥有的:

报表:
项目(字符串)
角色(字符串数组)

员工表:
项目(字符串数组)//员工工作/从事的所有项目
角色(字符串数组)//员工可以有多个角色

在查询员工可以看到的报告时,我会这样做:

select * 
from reports 
WHERE (employee.roles && report.roles) AND (report.project = ANY (employee.projects))

我用的是postgresql

问题是我认为这不会有很好的表现(我不确定)
我知道加快此查询的唯一方法是在报告(角色)列上创建 GIN 索引,以使重叠更快

除了性能这个技巧here,只是让我担心:

提示:数组不是集合;搜索特定的数组元素可能是数据库设计错误的标志。考虑使用一个单独的表,其中每个项目将是一个数组元素。这将更容易搜索,并且对于大量元素可能会更好地扩展。

那么有没有更好的设计来做到这一点,或者这样就可以正常工作?

【问题讨论】:

    标签: sql arrays database postgresql database-design


    【解决方案1】:

    简短的回答:您正在做的事情相当理智,但请考虑使用 int 数组而不是字符串,因为它们比较起来更快,并注意警告。

    就我个人而言,我会对其进行规范化:添加一个 user_roles 表,以及 role2report 和 user2role。就性能而言,根据我自己的经验,最佳情况是在您的应用中预先计算当前用户的 role_ids,然后使用 IN 子句查询角色。这意味着:

    select from reports join role2report ...
    

    在触发器等方面也是如此:关键是计算 role_ids(或 perm_ids)和 then 查询。在任何情况下,您都不希望:

    select from reports join role2report join crazy_user2role_role2role_rec_view
    

    从那里最大的优化涉及使用 int 数组或 memcached 或其他任何方式缓存用户角色以方便使用。这避免了不断使用疯狂的 user2role 和递归的 role2role 视图定义,以及你的规范的边缘情况导致你的任何其他类型的疯狂。思维缓存失效。

    根据我的经验,缓存访问列表要复杂得多:您应该缓存谁可以读取吗?写?两个都?有些对象是公开的吗?未登录的客人可以访问它们吗?这是一大堆问题。

    如果你缓存它,也可以使用 int 数组。扔进去例如-1 代表公共/访客访问,0 代表注册/用户访问。然后在查询中使用数组重叠(注册用户自动获得第 0 行和第 -1 行)。相应地优化你的数组以保持它们的小:如果它包含 -1,那应该是唯一的值;否则为零;否则列出具有授予访问权限的角色 ID。

    使用数组的一个警告,顺便说一句:至少在最新版本的 Postgres 之前(现在不确定),没有收集关于数组内容的统计信息。这使得对数据集使用数组不是最佳的,在这些数据集中,可以访问大多数事物的特定角色 ID 应该导致 Postgres 忽略 GIN 索引。这是一个真正的性能杀手,因为这意味着 PG 基本上将获取整个表以获取具有适当权限的前 10 行,而不是使用过滤器对其进行索引扫描。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-20
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多