Files
Oxicloud/migrations/20260921000000_users_created_at_index.sql
T
2026-07-22 02:06:29 +02:00

29 lines
2.0 KiB
SQL

-- no-transaction
-- Paginated admin user listings sort newest-first with `id` as a stable
-- tiebreaker. PostgreSQL 13+ uses this timestamp index plus an incremental
-- sort only within equal-timestamp groups. Without the index,
-- PostgreSQL scans and top-N sorts the entire user directory for every page.
-- Keep the index narrow: the compact response fetches at most 500 heap rows,
-- while INCLUDE-ing profile columns would bloat both RAM and write I/O.
-- The initial 500k-row fixture with 100-way timestamp ties was superseded for
-- resource accounting because B-tree posting-list dedup compressed its keys.
-- Three independent representative A/B transactions (15 samples/shape, common
-- UUID PK) measured mostly-unique timestamps at 11,255,808 bytes and +0.680 us
-- per inserted user; first/deep pages improved 266.13x/24.21x. Ten-user bursts
-- used 4,751,360 bytes and +0.582 us/user, improving reads 321.57x/18.29x.
-- (`tools/perf-audit/admin_user_order_index_representative.sql`). The user
-- explicitly accepted those corrected costs. This migration deliberately
-- remains one-column. A later isolated representative A/B/C gate rejected the
-- compound index: it regressed the common unique-timestamp first page by 6.45%,
-- increased index bytes by 80.13%-327.76%, and added 0.445 us/user to burst
-- inserts despite improving deep pages by 1.63x-2.30x.
-- Build online: a regular CREATE INDEX would block INSERT/UPDATE/DELETE on
-- auth.users (including the last_login_at write) for the full build. Keep this
-- as the migration's only statement: PostgreSQL wraps multiple statements from
-- one simple-query message in an implicit transaction, where CONCURRENTLY is
-- forbidden. If a failed build leaves this name INVALID, operators must run
-- `DROP INDEX CONCURRENTLY auth.idx_users_created_at_desc` before retrying;
-- deliberately omit IF NOT EXISTS so an invalid index is never accepted.
CREATE INDEX CONCURRENTLY idx_users_created_at_desc
ON auth.users (created_at DESC);