Postgresql – How to avoid large joins when determining which rows a user is authorized for

access-controlauthorizationjoin;performancepostgresql

Typical wep app situation: you have logged in users querying for resources exposed through an API. As a hypothetical example, company administrators quering for their employees' time sheets:

company <- employees <- time_sheets
company <- admin

Say I wanted to get all the time sheets that I'm authorized for/I have access to as an admin of that company.

Without any optimizations, in the above I'd have to join admin with company with employees with time_sheets to determine all the time_sheets I can look at. You can see how for a wider schema the joins could add up very fast. I realize that in modern databases joins are ludicrously fast, but I'm guessing this is still a case you don't want to completely ignore.

Is there a good solution to this? One could potentially have a separate admin to time_sheets many to many join table just to speed-up those queries, but then maintaining it might be tricky.

Any suggestions?

Best Answer

Like most things it's all about trade-offs. You can denormalize, maintain materialized views, etc, but all that has its own costs. It really depends on workload, query patterns, response time priorities, maintenance burden you're willing to bear, etc.

In general I'd recommend starting with the properly normalized design and join chain, but doing it via views for common queries. This allows you to later replace the view with a trigger-maintained materialized view, to selectively denormalize the schema, etc, without messing with the app's queries.

Don't try to fix it until you know it's actually a problem.