perf + simpler: composite index, range-filtered protokoll, simpler profile
- Migration v9 adds idx_applications_user_flat_started on (user_id, flat_id, started_at DESC). Covers latest_applications_by_flat inner GROUP BY and the outer JOIN without a table scan. - Push the protokoll date range into SQL instead of pulling 5000 rows into Python and filtering there: new audit_in_range / errors_in_range helpers with a shared _range_filter_rows impl. Protokoll page limits 500, CSV export 5000. - _row_to_profile collapses to `dict(profile_row)`. ProfileModel (Pydantic) already validates and coerces types on the apply side, extras ignored. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
eb73b5e415
commit
cb617dd38a
3 changed files with 47 additions and 26 deletions
35
web/db.py
35
web/db.py
|
|
@ -260,6 +260,11 @@ MIGRATIONS: list[str] = [
|
|||
CREATE INDEX IF NOT EXISTS idx_partnerships_from ON partnerships(from_user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnerships_to ON partnerships(to_user_id);
|
||||
""",
|
||||
# 0009: composite index for latest_applications_by_flat + last_application_for_flat
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS idx_applications_user_flat_started
|
||||
ON applications(user_id, flat_id, started_at DESC);
|
||||
""",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -780,6 +785,36 @@ def recent_audit(user_id: Optional[int], limit: int = 100) -> list[sqlite3.Row]:
|
|||
).fetchall())
|
||||
|
||||
|
||||
def _range_filter_rows(table: str, ts_col: str, start_iso: Optional[str],
|
||||
end_iso: Optional[str], limit: int) -> list[sqlite3.Row]:
|
||||
"""Date-range filtered fetch from an append-only table. Pushes the
|
||||
timestamp filter into SQL so we don't drag 5000 rows into Python just
|
||||
to discard most of them."""
|
||||
clauses, params = [], []
|
||||
if start_iso:
|
||||
clauses.append(f"{ts_col} >= ?")
|
||||
params.append(start_iso)
|
||||
if end_iso:
|
||||
clauses.append(f"{ts_col} < ?")
|
||||
params.append(end_iso)
|
||||
where = ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
||||
params.append(limit)
|
||||
return list(_get_conn().execute(
|
||||
f"SELECT * FROM {table} {where} ORDER BY {ts_col} DESC LIMIT ?",
|
||||
params,
|
||||
).fetchall())
|
||||
|
||||
|
||||
def audit_in_range(start_iso: Optional[str], end_iso: Optional[str],
|
||||
limit: int = 500) -> list[sqlite3.Row]:
|
||||
return _range_filter_rows("audit_log", "timestamp", start_iso, end_iso, limit)
|
||||
|
||||
|
||||
def errors_in_range(start_iso: Optional[str], end_iso: Optional[str],
|
||||
limit: int = 500) -> list[sqlite3.Row]:
|
||||
return _range_filter_rows("errors", "timestamp", start_iso, end_iso, limit)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Retention cleanup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue