Fix Supabase linter performance findings
- add covering indexes for flagged foreign keys - optimize RLS policies to use select auth.uid() - consolidate posts update policies into one permissive rule - document linter findings and decisions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Database performance notes (Supabase linter)
|
||||
|
||||
This project had two performance-related linter groups:
|
||||
|
||||
1. **RLS auth function evaluation**
|
||||
2. **Unindexed foreign keys**
|
||||
|
||||
## What was changed
|
||||
|
||||
1. Added migration `infrastructure/migrations/002_perf_linter_fixes.sql`.
|
||||
2. Updated `infrastructure/migrations/001_schema.sql` to keep fresh setups aligned with the same fixes.
|
||||
|
||||
### RLS changes
|
||||
|
||||
The affected policies now use:
|
||||
|
||||
- `(select auth.uid())` instead of `auth.uid()`
|
||||
|
||||
This avoids repeated per-row evaluation in RLS plans for these policies:
|
||||
|
||||
- `profiles_update`
|
||||
- `posts_select`
|
||||
- `posts_insert`
|
||||
- `posts_update_own`
|
||||
- `resonances_insert`
|
||||
- `resonances_delete`
|
||||
- `whispers_select`
|
||||
- `whispers_insert`
|
||||
- `follows_insert`
|
||||
- `follows_delete`
|
||||
- `reports_insert`
|
||||
- `reports_select_own`
|
||||
|
||||
Also, duplicate permissive update policies on `public.posts` were consolidated by removing `posts_softdelete` and keeping a single `posts_update_own`.
|
||||
|
||||
### FK index changes
|
||||
|
||||
Added covering indexes:
|
||||
|
||||
- `idx_follows_following_id` on `public.follows(following_id)`
|
||||
- `idx_reports_reporter_id` on `public.reports(reporter_id)`
|
||||
- `idx_resonances_user_id` on `public.resonances(user_id)`
|
||||
- `idx_whispers_from_user_id` on `public.whispers(from_user_id)`
|
||||
- `idx_whispers_post_id` on `public.whispers(post_id)`
|
||||
|
||||
## About "unused index" findings
|
||||
|
||||
`unused_index` is based on `pg_stat_user_indexes.idx_scan`, which can read as zero after restarts or during low traffic.
|
||||
In this environment, PostgreSQL was recently restarted, so these were not dropped automatically.
|
||||
|
||||
Suggested review query:
|
||||
|
||||
```sql
|
||||
select
|
||||
schemaname,
|
||||
relname as table_name,
|
||||
indexrelname as index_name,
|
||||
idx_scan
|
||||
from pg_stat_user_indexes
|
||||
where schemaname = 'public'
|
||||
order by idx_scan asc, indexrelname;
|
||||
```
|
||||
|
||||
Drop an index only after observing sustained zero usage over representative production traffic.
|
||||
Reference in New Issue
Block a user