perf(database): index BatchTaskRun on (runtimeEnvironmentId, createdAt, id) for the batches list (#4361)

## Summary

The batches list page orders by `createdAt DESC, id DESC` filtered by
environment and a created-at window, but the only supporting index on
`BatchTaskRun` was `(runtimeEnvironmentId, id)`. That index can't
satisfy the `createdAt` ordering, so on environments with a large number
of batches the query fell back to a full table scan and in-memory sort,
which could run long enough to hit the statement timeout.

## Fix

Adds `(runtimeEnvironmentId, createdAt DESC, id DESC)` on
`BatchTaskRun`. The query now reads straight from the index in order
with no sort step, returning a page with only a handful of heap fetches
instead of scanning the whole environment slice.

The migration uses `CREATE INDEX CONCURRENTLY IF NOT EXISTS`, so it
takes no table lock and is a no-op if the index already exists.
This commit is contained in:
Eric Allam
2026-07-24 11:52:34 +01:00
committed by GitHub
parent 722e240e4d
commit 9c85e0ecdc
3 changed files with 9 additions and 0 deletions
@@ -0,0 +1,6 @@
---
area: webapp
type: fix
---
Speed up the Batches list page for environments with a large number of batches, which could previously time out while loading.
@@ -0,0 +1,2 @@
-- CreateIndex
CREATE INDEX CONCURRENTLY IF NOT EXISTS "BatchTaskRun_runtimeEnvironmentId_createdAt_id_idx" ON "public"."BatchTaskRun"("runtimeEnvironmentId", "createdAt" DESC, "id" DESC);
@@ -1935,6 +1935,7 @@ model BatchTaskRun {
@@index([dependentTaskAttemptId])
// This is for the batch list dashboard page
@@index([runtimeEnvironmentId, id(sort: Desc)])
@@index([runtimeEnvironmentId, createdAt(sort: Desc), id(sort: Desc)])
}
enum BatchTaskRunStatus {