-- Index backing the back-office "banned accounts" surface
-- (`GET /admin/users/banned`, via `UserRepository::listForAdmin(banned: true)`).
--
-- That listing filters on an ACTIVE ban (`banned_until IS NOT NULL AND
-- banned_until > NOW()`) then sorts `joined_at DESC, id DESC LIMIT n`. With no
-- index on `banned_until`, MySQL chose a *backward index scan* on `joined_at`
-- and walked almost the entire `user` table (~990k rows) to surface the handful
-- of banned accounts — the endpoint timed out.
--
-- A plain single-column index on `banned_until` turns the predicate into a
-- range scan (`type=range`, ~1 row), and the tiny matching set is ordered with
-- a trivial filesort. The optimiser now picks `idx_banned_until` on its own; no
-- FORCE INDEX hint is needed. Query time drops from a timeout to sub-millisecond.
--
-- Write cost is one extra B-tree entry per ban/unban — negligible on a column
-- that changes rarely.

ALTER TABLE `user`
    ADD INDEX `idx_banned_until` (`banned_until`);
