The default page (no search words) took 23-27 s: SearchService sorts posted_at DESC NULLS LAST, id DESC, the indexes were on posted_at DESC (nulls first), so Postgres sorted all 68M releases. New indexes match the sort (also per category), built concurrently; the old ones dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
26 lines
1.3 KiB
TypeScript
26 lines
1.3 KiB
TypeScript
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
|
|
/**
|
|
* Indexes that match the newest-first sort (SearchService: posted_at DESC
|
|
* NULLS LAST, id DESC). The old ones (posted_at DESC: nulls first) didn't,
|
|
* so the default page sorted all 68M releases: 23 s. Built concurrently, the
|
|
* old ones dropped after.
|
|
*/
|
|
export default class extends BaseSchema {
|
|
static disableTransactions = true
|
|
|
|
async up() {
|
|
this.schema.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS releases_newest_idx ON releases (posted_at DESC NULLS LAST, id DESC)`)
|
|
this.schema.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS releases_category_newest_idx ON releases (category, posted_at DESC NULLS LAST, id DESC)`)
|
|
this.schema.raw(`DROP INDEX CONCURRENTLY IF EXISTS releases_posted_at_idx`)
|
|
this.schema.raw(`DROP INDEX CONCURRENTLY IF EXISTS releases_category_posted_idx`)
|
|
}
|
|
|
|
async down() {
|
|
this.schema.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS releases_posted_at_idx ON releases (posted_at DESC)`)
|
|
this.schema.raw(`CREATE INDEX CONCURRENTLY IF NOT EXISTS releases_category_posted_idx ON releases (category, posted_at DESC)`)
|
|
this.schema.raw(`DROP INDEX CONCURRENTLY IF EXISTS releases_newest_idx`)
|
|
this.schema.raw(`DROP INDEX CONCURRENTLY IF EXISTS releases_category_newest_idx`)
|
|
}
|
|
}
|