Fix notification query plan for users with domain blocks #7981

Merged
lambadalambda merged 2 commits from fix/domain-block-subplan-cost into develop 2026-09-02 13:41:41 +00:00

keep_following_or_not_domain_blocked/2 uses ? = ANY(SELECT ap_id FROM users JOIN following_relationships ...). Postgres folds that hashed sub-plan's startup cost into the actor index scan and charges it on every rescan of the nested loop, so for a user with a long follow list the index plan is estimated ~1000x too high and can lose to a plan that materialises every active user per candidate row.

Wrapping the subselect in ARRAY(...) makes it an InitPlan, evaluated and costed once.

Measured on a 312 GB instance, /api/v1/notifications for a user with 20k notifications and 2.3k follows:

planner cost actual
materialise-users plan (chosen at work_mem 64MB) 339,878 3.8 s
index plan, before 373,199 74 ms
index plan, after 17,255 4.8 ms

Adds a test for the followed-actor exception through Notification.for_user/1.

`keep_following_or_not_domain_blocked/2` uses `? = ANY(SELECT ap_id FROM users JOIN following_relationships ...)`. Postgres folds that hashed sub-plan's startup cost into the actor index scan and charges it on every rescan of the nested loop, so for a user with a long follow list the index plan is estimated ~1000x too high and can lose to a plan that materialises every active user per candidate row. Wrapping the subselect in `ARRAY(...)` makes it an InitPlan, evaluated and costed once. Measured on a 312 GB instance, `/api/v1/notifications` for a user with 20k notifications and 2.3k follows: | | planner cost | actual | |---|---|---| | materialise-users plan (chosen at work_mem 64MB) | 339,878 | 3.8 s | | index plan, before | 373,199 | 74 ms | | index plan, after | 17,255 | 4.8 ms | Adds a test for the followed-actor exception through `Notification.for_user/1`.
fix(notifications): cost the followed-accounts subselect once
All checks were successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/unit-testing-elixir-1.15 Pipeline was successful
ci/woodpecker/pr/unit-testing-elixir-1.19 Pipeline was successful
635bc19ac8
Wrap the followed ap_ids subselect in keep_following_or_not_domain_blocked
in ARRAY(...) so it becomes an InitPlan. As a plain subselect the planner
charged its startup per rescan of the actor lookup, which could make
Notification.for_user pick a plan that scans every active user per row.
Merge branch 'develop' into fix/domain-block-subplan-cost
All checks were successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/unit-testing-elixir-1.19 Pipeline was successful
ci/woodpecker/pr/unit-testing-elixir-1.15 Pipeline was successful
70d743bff9
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pleroma/pleroma!7981
No description provided.