- track_plays(played_at,track_id,station_id) покрывающий + tracks(first_seen_at) WHERE pending частичный (применены CONCURRENTLY на проде + миграция idempotent) - ChartsService.getTopTracks: in-memory TTL-кэш 90с по (period,genre,limit) → детальная страница и параллельные запросы не пересчитывают тяжёлые агрегации - NowPlayingService.ingest: не пишем now_playing и не шлём сокет, если трек не изменился (было ~20k бесполезных upsert/час) - enrichNowPlaying: вместо N+1 (300 upsert/мин) — один batched findMany по normKey Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 lines
533 B
SQL
6 lines
533 B
SQL
-- Покрывающий индекс под агрегацию чартов (идемпотентно — на проде уже создан CONCURRENTLY).
|
|
CREATE INDEX IF NOT EXISTS "track_plays_window_idx" ON "track_plays" ("played_at", "track_id", "station_id");
|
|
|
|
-- Частичный индекс под бэкфилл обогащения (Prisma не выражает partial WHERE в схеме).
|
|
CREATE INDEX IF NOT EXISTS "tracks_enrich_pending_idx" ON "tracks" ("first_seen_at" DESC) WHERE "enrich_status" = 'pending';
|