From 3d88676bbe9d24d2b5b2d8d26bff6bb7f2549825 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Fri, 18 Sep 2026 20:28:14 +0200 Subject: [PATCH] perf: index the legacy audit table by operation too Co-Authored-By: Claude Opus 5 (1M context) --- ...itioned_workspace_operation_index.down.sql | 1 + ...rtitioned_workspace_operation_index.up.sql | 6 +++-- backend/windmill-api/src/db.rs | 25 ++++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.down.sql b/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.down.sql index ebe897537f..e9104f4d1c 100644 --- a/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.down.sql +++ b/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.down.sql @@ -1 +1,2 @@ DROP INDEX IF EXISTS ix_audit_partitioned_workspace_operation; +DROP INDEX IF EXISTS ix_audit_workspace_operation; diff --git a/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.up.sql b/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.up.sql index 4d07e66f5a..74aa7340a6 100644 --- a/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.up.sql +++ b/backend/migrations/20260918173412_audit_partitioned_workspace_operation_index.up.sql @@ -1,6 +1,8 @@ --- The backend builds this per partition with CREATE INDEX CONCURRENTLY instead, --- see create_audit_operation_index_concurrently in windmill-api/src/db.rs. +-- The backend builds these with CREATE INDEX CONCURRENTLY instead (per partition for +-- audit_partitioned), see create_audit_operation_index_concurrently in windmill-api/src/db.rs. -- id matches list_audit's order and before_id cursor. timestamp trails it so a -- time window is checked in the index rather than on every row it reads. +CREATE INDEX IF NOT EXISTS ix_audit_workspace_operation + ON audit (workspace_id, operation, id DESC, "timestamp"); CREATE INDEX IF NOT EXISTS ix_audit_partitioned_workspace_operation ON audit_partitioned (workspace_id, operation, id DESC, "timestamp"); diff --git a/backend/windmill-api/src/db.rs b/backend/windmill-api/src/db.rs index fd6ee24e56..fbb8b29415 100644 --- a/backend/windmill-api/src/db.rs +++ b/backend/windmill-api/src/db.rs @@ -40,6 +40,27 @@ const AUDIT_OPERATION_INDEX_KEY: &str = r#"(workspace_id, operation, id DESC, "t async fn create_audit_operation_index_concurrently( conn: &mut PgConnection, ) -> Result<(), MigrateError> { + // list_audit reads the legacy table too, which holds up to a retention period of rows + // written before partitioning. + let legacy_valid: Option = sqlx::query_scalar( + "SELECT indisvalid FROM pg_index + WHERE indexrelid = to_regclass('ix_audit_workspace_operation')", + ) + .fetch_optional(&mut *conn) + .await?; + if legacy_valid != Some(true) { + conn.execute("DROP INDEX CONCURRENTLY IF EXISTS ix_audit_workspace_operation") + .await?; + conn.execute( + format!( + "CREATE INDEX CONCURRENTLY ix_audit_workspace_operation \ + ON audit {AUDIT_OPERATION_INDEX_KEY}" + ) + .as_str(), + ) + .await?; + } + conn.execute( format!( "CREATE INDEX IF NOT EXISTS ix_audit_partitioned_workspace_operation \ @@ -61,7 +82,9 @@ async fn create_audit_operation_index_concurrently( .await?; let quote = |name: &str| format!("\"{}\"", name.replace('"', "\"\"")); for partition in partitions { - let index = quote(&format!("{partition}_workspace_id_operation_id_timestamp_idx")); + let index = quote(&format!( + "{partition}_workspace_id_operation_id_timestamp_idx" + )); tracing::info!("Building ix_audit_partitioned_workspace_operation on {partition}"); // An interrupted CONCURRENTLY build leaves an invalid index under this name. conn.execute(format!("DROP INDEX CONCURRENTLY IF EXISTS {index}").as_str())