From 5130f754cc6b155299dd94900d781e436013bf7a Mon Sep 17 00:00:00 2001 From: rays Date: Sat, 17 Oct 2026 14:17:56 +0000 Subject: [PATCH] Analyse entries once when entries_recent has no statistics (#274) Deployed, the judge's query still read every entry: an expression index has no statistics until its table is analysed, and Postgres, guessing a third of entries were recent, chose a scan (898 ms) over entries_recent. Co-Authored-By: Claude Opus 5.5 --- crates/ipx/src/db.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/ipx/src/db.rs b/crates/ipx/src/db.rs index b6055e8..955b03e 100644 --- a/crates/ipx/src/db.rs +++ b/crates/ipx/src/db.rs @@ -117,6 +117,15 @@ async fn create_missing(orm: &sea_orm::DatabaseConnection) -> Result<()> { orm.execute_unprepared(sql).await.with_context(|| sql.to_owned())?; } } + // An expression index has no statistics until its table is analysed, and without them + // Postgres guessed a third of entries were recent and read them all, entries_recent unused + // (#274). Analysed once when they are missing; autovacuum keeps them after. + if orm.get_database_backend() == sea_orm::DbBackend::Postgres { + let has = Statement::from_string(sea_orm::DbBackend::Postgres, "SELECT 1 FROM pg_stats WHERE tablename = 'entries_recent'"); + if orm.query_one_raw(has).await?.is_none() { + orm.execute_unprepared("ANALYZE entries").await.context("analysing entries")?; + } + } if orm.execute_unprepared("SELECT recheck FROM signal_verdicts LIMIT 0").await.is_err() { let sql = "ALTER TABLE signal_verdicts ADD COLUMN recheck BOOLEAN NOT NULL DEFAULT false"; orm.execute_unprepared(sql).await.with_context(|| sql.to_owned())?;