mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 18:35:07 +03:00
Apply feedback
- Remove benchmarks - Remove 'This guide' from beginning of topic
This commit is contained in:
1 parent
1ae99901a4
commit
3a77f5bb1c
2 files changed
+3
-19
No files matched your search
@@ -5,11 +5,11 @@ description: 'Measure and tune Postgres Row Level Security policies.'
|
||||
subtitle: 'Measure and tune Postgres Row Level Security policies.'
|
||||
---
|
||||
|
||||
This guide explains how to measure the cost of Row Level Security (RLS) and tune policies that are already correct. To learn how to write correct policies, see [Row Level Security](/docs/guides/database/postgres/row-level-security).
|
||||
Measure the cost of Row Level Security (RLS) and tune policies that are already correct. To learn how to write correct policies, see [Row Level Security](/docs/guides/database/postgres/row-level-security).
|
||||
|
||||
Postgres evaluates a policy expression against each candidate row, so the cost scales with the rows a query scans. This matters most for queries that scan every row in a table, like many `select` operations, including those using limit, offset, and ordering.
|
||||
|
||||
Three policy rules affect performance enough that they belong with the policy itself rather than here. The RLS guide covers each one, and the [benchmarks](#benchmarks) on this page measure them:
|
||||
Three policy rules affect performance enough that they belong with the policy itself rather than here. Apply them first:
|
||||
|
||||
- [Index the columns your policies filter on](/docs/guides/database/postgres/row-level-security#add-indexes)
|
||||
- [Call functions with `select`](/docs/guides/database/postgres/row-level-security#call-functions-with-select)
|
||||
@@ -148,22 +148,6 @@ If the list exceeds 1000 items, a different approach may be needed, or you may n
|
||||
|
||||
</Admonition>
|
||||
|
||||
## Benchmarks
|
||||
|
||||
These numbers come from a series of [tests](https://github.com/GaryAustin1/RLS-Performance) run against a 100,000-row table. Each row links to the test that produced it.
|
||||
|
||||
| Test | Before (ms) | After (ms) | % Improvement | Change |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------- | ----------- | ---------- | ------------- | ----------------------------------------------------------------------------------- |
|
||||
| [test1-indexed](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test1-indexed) | 171 | < 0.1 | 99.94% | No index, then `user_id` indexed |
|
||||
| [test2a-wrappedSQL-uid](<https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test2a-wrappedSQL-uid()>) | 179 | 9 | 94.97% | `auth.uid() = user_id`, then `(select auth.uid()) = user_id` |
|
||||
| [test2b-wrappedSQL-isadmin](<https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test2b-wrappedSQL-isadmin()>) | 11,000 | 7 | 99.94% | `is_admin()` table join, then `(select is_admin())` table join |
|
||||
| [test2c-wrappedSQL-two-functions](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test2c-wrappedSQL-two-functions) | 11,000 | 10 | 99.91% | Two bare function calls, then both wrapped in `select` |
|
||||
| [test2d-wrappedSQL-sd-fun](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test2d-wrappedSQL-sd-fun) | 178,000 | 12 | 99.993% | `has_role() = role`, then `(select has_role()) = role` |
|
||||
| [test2e-wrappedSQL-sd-fun-array](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test2e-wrappedSQL-sd-fun-array) | 173,000 | 16 | 99.991% | `team_id = any(user_teams())`, then `team_id = any(array(select user_teams()))` |
|
||||
| [test3-addfilter](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test3-addfilter) | 171 | 9 | 94.74% | No client filter, then `.eq` or `where` on `user_id` |
|
||||
| [test5-fixed-join](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test5-fixed-join) | 9,000 | 20 | 99.78% | `auth.uid()` in a table join on a column, then the column in a join on `auth.uid()` |
|
||||
| [test6-To-role](https://github.com/GaryAustin1/RLS-Performance/tree/main/tests/test6-To-role) | 170 | < 0.1 | 99.78% | No `to` clause, then `to authenticated` with `anon` accessing |
|
||||
|
||||
## More resources
|
||||
|
||||
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
|
||||
|
||||
@@ -639,7 +639,7 @@ using ( (select auth.uid()) = user_id );
|
||||
|
||||
This prevents the policy `( (select auth.uid()) = user_id )` from running for any `anon` users, since the execution stops at the `to authenticated` step.
|
||||
|
||||
These three rules keep policies correct as a table grows. For the measured impact and for tuning beyond them, see [Row Level Security performance](/docs/guides/database/postgres/row-level-security-performance).
|
||||
These three rules keep policies correct as a table grows. To diagnose whether a policy is still the bottleneck, and to tune beyond these rules, see [Row Level Security performance](/docs/guides/database/postgres/row-level-security-performance).
|
||||
|
||||
### Use security definer functions
|
||||
|
||||
|
||||
Reference in new issue
Block a user