fix: add partial index for fast failure filtering on runs page (#8150)

When failures are sparse (<1%), filtering by failure status on the runs
page required scanning millions of success rows. Add a partial index on
v2_job_completed (workspace_id, completed_at DESC) WHERE status IN
('failure', 'canceled') and switch ORDER BY to completed_at when
filtering failures, so Postgres walks the small partial index directly.

Benchmarked at 5.2M rows / 1% failure rate:
- LIMIT 30:   800ms -> 0.4ms (2000x faster)
- LIMIT 1000: 550ms -> 21ms  (26x faster)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-02-28 18:18:34 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 59e51ac097
commit d4673c2e91
4 changed files with 15 additions and 1 deletions
@@ -0,0 +1 @@
DROP INDEX IF EXISTS ix_v2_job_completed_failure_workspace;
@@ -0,0 +1,7 @@
-- Partial index for fast failure/canceled filtering on the runs page.
-- When failures are sparse (<1%) this avoids scanning millions of successful jobs.
-- The query orders by completed_at DESC (switched from created_at when success=false),
-- so this index provides both filtering and ordering in a single scan.
CREATE INDEX IF NOT EXISTS ix_v2_job_completed_failure_workspace
ON v2_job_completed (workspace_id, completed_at DESC)
WHERE status IN ('failure', 'canceled');
+4 -1
View File
@@ -556,7 +556,10 @@ pub fn list_completed_jobs_query(
let mut sqlb = SqlBuilder::select_from("v2_job_completed")
.fields(fields)
.order_by(
if lq.completed_before.is_some() || lq.completed_after.is_some() {
if lq.completed_before.is_some()
|| lq.completed_after.is_some()
|| lq.success == Some(false)
{
"v2_job_completed.completed_at"
} else {
"v2_job.created_at"
+3
View File
@@ -81,6 +81,9 @@ lazy_static::lazy_static! {
(20260225100000, include_str!(
"../../migrations/20260225100000_asset_covering_index.up.sql"
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),
(20260228000000, include_str!(
"../../migrations/20260228000000_v2_job_completed_failure_index.up.sql"
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY")),
].into_iter().collect();
}