From 0ddeaf1896a51efa016eaf32fc593562bbf66915 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Wed, 4 Feb 2026 21:54:27 +0100 Subject: [PATCH] Add migration for performance indexes The indexes defined in models.py __table_args__ are not automatically created by the custom migration system. Added migrate_performance_indexes() to explicitly create the indexes at startup. Co-Authored-By: Claude Opus 4.5 --- .../src/backend/app/migrations.py | 41 +++++++++++++++++++ docs/changelog-claude.md | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/containers/backupchecks/src/backend/app/migrations.py b/containers/backupchecks/src/backend/app/migrations.py index 80061d7..de5c0d9 100644 --- a/containers/backupchecks/src/backend/app/migrations.py +++ b/containers/backupchecks/src/backend/app/migrations.py @@ -930,6 +930,7 @@ def run_migrations() -> None: migrate_news_tables() migrate_reporting_tables() migrate_reporting_report_config() + migrate_performance_indexes() print("[migrations] All migrations completed.") @@ -1114,6 +1115,46 @@ def migrate_jobs_archiving() -> None: print("[migrations] migrate_jobs_archiving completed.") +def migrate_performance_indexes() -> None: + """Add performance indexes for frequently queried foreign key columns. + + These indexes significantly improve query performance on slow storage, + especially for Daily Jobs and Run Checks pages. + + This migration is idempotent. + """ + try: + engine = db.get_engine() + except Exception as exc: + print(f"[migrations] Could not get engine for performance indexes migration: {exc}") + return + + with engine.begin() as conn: + # JobRun indexes + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_job_run_job_id ON job_runs (job_id)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_job_run_job_id_run_at ON job_runs (job_id, run_at)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_job_run_job_id_reviewed_at ON job_runs (job_id, reviewed_at)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_job_run_mail_message_id ON job_runs (mail_message_id)')) + + # MailMessage indexes + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_mail_message_job_id ON mail_messages (job_id)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_mail_message_location ON mail_messages (location)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_mail_message_job_id_location ON mail_messages (job_id, location)')) + + # MailObject indexes + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_mail_object_mail_message_id ON mail_objects (mail_message_id)')) + + # TicketScope indexes + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_ticket_scope_ticket_id ON ticket_scopes (ticket_id)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_ticket_scope_job_id ON ticket_scopes (job_id)')) + + # RemarkScope indexes + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_remark_scope_remark_id ON remark_scopes (remark_id)')) + conn.execute(text('CREATE INDEX IF NOT EXISTS idx_remark_scope_job_id ON remark_scopes (job_id)')) + + print("[migrations] migrate_performance_indexes completed.") + + def migrate_reporting_report_config() -> None: """Add report_definitions.report_config column if missing. diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 7f3071e..b0c8248 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -13,7 +13,7 @@ This file documents all changes made to this project via Claude Code. - Filled README.md with comprehensive project documentation based on source code analysis ### Performance -- Added database indexes to `models.py` for frequently queried foreign key columns: +- Added database indexes migration (`migrations.py`) for frequently queried foreign key columns: - `JobRun`: indexes on `job_id`, `job_id+run_at`, `job_id+reviewed_at`, `mail_message_id` - `MailMessage`: indexes on `job_id`, `location`, `job_id+location` - `MailObject`: index on `mail_message_id`