perf(PROJ-75): Partial Index gegen Seq-Scan in GetUnindexedMails

Der index-pending-Cron (PROJ-58) scannte bei jedem Lauf die komplette
emails-Tabelle, weil indexed_at unindiziert war — skaliert linear mit
Archivgröße. Partial Index auf (received_at DESC) WHERE indexed_at IS NULL
verifiziert auf 192.168.1.132: Seq Scan (13.3ms, 52895 Zeilen) → Index Scan
(0.086ms).

Restlicher PROJ-75-Audit (pgxpool-Tuning, reconciliation N+1) bewusst
zurückgestellt, siehe Feature-Spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
This commit is contained in:
sysops
2026-08-05 14:55:13 +02:00
co-authored by Claude Sonnet 5
parent 075afa005a
commit c75352839c
4 changed files with 217 additions and 1 deletions
+3
View File
@@ -100,6 +100,9 @@ func New(cfg Config) (*Store, error) {
// PROJ-34: GoBD retention lock
_, _ = s.db.Exec(ctx, `ALTER TABLE emails ADD COLUMN IF NOT EXISTS retain_until TIMESTAMPTZ`)
_, _ = s.db.Exec(ctx, `CREATE INDEX IF NOT EXISTS idx_emails_retain_until ON emails (retain_until) WHERE retain_until IS NOT NULL`)
// PROJ-75: partial index for GetUnindexedMails (index-pending cron, PROJ-58) — avoids
// full seq scan over emails on every run once indexed_at is set for most rows.
_, _ = s.db.Exec(ctx, `CREATE INDEX IF NOT EXISTS idx_emails_unindexed ON emails (received_at DESC) WHERE indexed_at IS NULL`)
// PROJ-33: Stable IMAP UIDs
_, _ = s.db.Exec(ctx, `ALTER TABLE emails ADD COLUMN IF NOT EXISTS uid BIGSERIAL`)
_, _ = s.db.Exec(ctx, `CREATE UNIQUE INDEX IF NOT EXISTS idx_emails_uid ON emails (uid)`)