We are using Postgres for RBAC permissions model with groups and trying to think on the best indexes needed, assuming our DB has the following schema:
Subjects Table
id, external_type, external_id, group_id
Resources Table
id, group_id, external_type, external_id, role_id
Both tables are meant to answer a single question:
Can subject [S] perform action [A] on resource [R]
So we need to retrieve all the roles a user has on a resource, from all the permission groups he takes part in.
- A subject can have K rows in the subjects table, one for each group he is a member at.
- A resource can have M rows in the resources table, one for every group a role was assigned for this resource.
- We chose to denormalize the resources, groups and roles in one table for read optimized performance.
- We chose not to denormalize also subjects in the same table - to avoid updating many records on every group structure change.
- Both K & M can be very big - a user can be in many groups, and a resource can belong to many groups.
So the query will be:
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
We decided on defining the following indexes:
Subjects: <external_type, external_id>, <group_id>
Resources: <external_type, external_id>, <group_id>
Can someone please explain how does inner join with where clause relates to 2 tables utilizes indexes? Are they performed parallel and then connected by the ON statement or only one table's indexes will be used for the where and then connected using the ON connection?
Should we use different compound indexes? add the group_id to the compound indexes somehow?
Any reference to a similar use case or choosing indexes for complex JOIN queries will be helpful.
role_idto the index for extra performance. This could marginally improve the performance.WHEREconditions on the respective queries, that is, how many rows will pass? How many rows will the actual query produce? I am asking for estimates.EXPLAINon it. 2) Although there could be many matches for each part of the where clause (matching <external_type, external_id> on each table), the intersection should return very few results - also answering your question @Laurenz Albe