【发布时间】:2020-10-09 17:31:37
【问题描述】:
假设我们的数据库具有以下架构,我们将 Postgres 用于 RBAC 权限模型和组,并尝试考虑所需的最佳索引:
科目表
id, external_type, external_id, group_id
资源表
id, group_id, external_type, external_id, role_id
两张表都旨在回答一个问题:
主体 [S] 能否对 资源 [R]
执行动作 [A]因此,我们需要从用户参与的所有权限组中检索用户在资源上的所有角色。
- 主题可以在主题表中拥有 K 行,他所在的每个组对应一个。
- 一个资源在资源表中可以有 M 行,每个组对应一个为该资源分配的角色。
- 我们选择对一张表中的资源、组和角色进行非规范化处理,以优化读取性能。
- 我们选择不对同一张表中的主题进行非规范化 - 以避免在每次组结构更改时更新许多记录。
- K 和 M 都可以很大 - 一个用户可以属于多个组,而一个资源可以属于多个组。
所以查询将是:
SELECT role_id
FROM resources
INNER JOIN subjects
ON resources.group_id=subjects.group_id
WHERE subjects.external_type="user" AND subjects.external_id=123
AND resources.external_type="order" AND resources.external_id=456
我们决定定义以下索引:
Subjects: <external_type, external_id>, <group_id>
Resources: <external_type, external_id>, <group_id>
有人可以解释一下与where 子句的内部连接如何与2 个表使用索引相关吗?它们是并行执行,然后通过ON 语句连接,还是只有一个表的索引将用于where,然后使用ON 连接?
我们应该使用不同的复合索引吗?以某种方式将group_id 添加到复合索引中?
任何对类似用例的引用或为复杂的JOIN 查询选择索引都会有所帮助。
【问题讨论】:
-
您的索引没问题。该查询将在 范围索引扫描 上使用 嵌套循环,然后在另一个表的索引上使用 索引搜索。在这种情况下,我认为哪个表是主要的还是次要的并不重要。现在:1)查询慢吗? 2) 查询返回多少行?这可能会影响堆读取,但应该不错。
-
这是真实的、真实的查询吗?如果是这样,您可以将
role_id添加到索引中以获得额外的性能。这可能会略微提高性能。 -
WHERE条件对各个查询的选择性如何,即会通过多少行?实际查询将产生多少行?我要求估价。 -
@TheImpaler 系统仍在开发中。 1) 我们正在努力创建一个测试用例并在上面运行
EXPLAIN。 2)尽管 where 子句的每个部分可能有很多匹配项(在每个表上匹配),但交集应该返回很少的结果 - 也回答你的问题@Laurenz Albe
标签: sql postgresql indexing left-join inner-join