First commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""Phase 12: Add performance indexes on high-filter columns
|
||||
|
||||
Revision ID: phase12_performance_indexes
|
||||
Revises: phase11_director_role
|
||||
Create Date: 2026-04-25
|
||||
|
||||
Rationale
|
||||
---------
|
||||
The following columns are filtered or ordered on every page load but had no
|
||||
DB index, causing full table scans as row counts grow:
|
||||
|
||||
inspections
|
||||
- status — filtered on list/dashboard/SLA queries
|
||||
- facility_id — filtered for customer-scoped views and reports
|
||||
- inspector_id — filtered for inspector-scoped views
|
||||
- inspection_date — used in all trend/score queries (ORDER BY, range filter)
|
||||
|
||||
issues
|
||||
- status — filtered on every issues list/dashboard load
|
||||
- severity — filtered in dashboard breakdown and issues list
|
||||
- assigned_to — filtered for inspector-scoped views
|
||||
- reported_at — used for ordering
|
||||
|
||||
Existence checks use information_schema so the migration is safe to re-run
|
||||
on any MySQL version (compatible back to 5.7).
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy import text
|
||||
|
||||
|
||||
def _index_exists(conn, table: str, index_name: str) -> bool:
|
||||
"""Return True if the named index already exists on the given table."""
|
||||
result = conn.execute(text(
|
||||
"SELECT COUNT(*) FROM information_schema.statistics "
|
||||
"WHERE table_schema = DATABASE() "
|
||||
" AND table_name = :table "
|
||||
" AND index_name = :index"
|
||||
), {'table': table, 'index': index_name})
|
||||
return result.scalar() > 0
|
||||
|
||||
|
||||
revision = 'phase12_performance_indexes'
|
||||
down_revision = 'phase11_director_role'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
# (table, index_name, column)
|
||||
INDEXES = [
|
||||
('inspections', 'ix_inspections_status', 'status'),
|
||||
('inspections', 'ix_inspections_facility_id', 'facility_id'),
|
||||
('inspections', 'ix_inspections_inspector_id', 'inspector_id'),
|
||||
('inspections', 'ix_inspections_inspection_date', 'inspection_date'),
|
||||
('issues', 'ix_issues_status', 'status'),
|
||||
('issues', 'ix_issues_severity', 'severity'),
|
||||
('issues', 'ix_issues_assigned_to', 'assigned_to'),
|
||||
('issues', 'ix_issues_reported_at', 'reported_at'),
|
||||
]
|
||||
|
||||
|
||||
def upgrade():
|
||||
conn = op.get_bind()
|
||||
for table, index_name, column in INDEXES:
|
||||
if not _index_exists(conn, table, index_name):
|
||||
op.execute(text(
|
||||
f'CREATE INDEX {index_name} ON {table} ({column})'
|
||||
))
|
||||
|
||||
|
||||
def downgrade():
|
||||
conn = op.get_bind()
|
||||
for table, index_name, _column in INDEXES:
|
||||
if _index_exists(conn, table, index_name):
|
||||
op.execute(text(
|
||||
f'DROP INDEX {index_name} ON {table}'
|
||||
))
|
||||
Reference in New Issue
Block a user