-- ============================================================================ -- Optimize Indexes for Peoples and ItemValues Tables -- Generated: 2026-03-05 -- Purpose: Reduce sequential scans on high-traffic tables -- ============================================================================ \pset pager off \echo '=========================================' \echo 'Optimizing Peoples and ItemValues Indexes' \echo '=========================================' \echo '' -- ============================================================================ -- 1. PEOPLES TABLE OPTIMIZATION -- ============================================================================ -- Current Issue: 144,299 sequential scans reading 13.7 BILLION rows -- Current Indexes: IX_Peoples_Name, PK_Peoples -- Target: Reduce sequential scans by 80%+ \echo '1. Creating Peoples Table Indexes...' \echo '-----------------------------------------' -- Index for queries filtering by Name (case-insensitive searches) -- Supports ILIKE/LIKE queries CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_peoples_name_lower ON library."Peoples" (LOWER("Name")) WHERE "Name" IS NOT NULL; -- Composite index for common join patterns (People -> Items) -- Supports queries that need both Id and Name CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_peoples_id_name ON library."Peoples" ("Id", "Name") WHERE "Name" IS NOT NULL; -- Index for external ID lookups (TMDB, IMDB, etc.) -- Supports metadata provider queries CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_peoples_providerid ON library."Peoples" ("ProviderIds") WHERE "ProviderIds" IS NOT NULL; \echo 'Peoples indexes created successfully!' \echo '' -- ============================================================================ -- 2. ITEMVALUES TABLE OPTIMIZATION -- ============================================================================ -- Current Issue: 506,048 sequential scans reading 3.7 BILLION rows -- Current Indexes: IX_ItemValues_Type_CleanValue, IX_ItemValues_Type_Value -- Target: Increase index usage from 82% to 95%+ \echo '2. Creating ItemValues Table Indexes...' \echo '-----------------------------------------' -- Index for CleanValue lookups without Type filter -- Supports genre/tag searches that don't filter by type CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_cleanvalue ON library."ItemValues" ("CleanValue") WHERE "CleanValue" IS NOT NULL; -- Index for Value lookups (with original casing) -- Supports exact value matches CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_value ON library."ItemValues" ("Value") WHERE "Value" IS NOT NULL; -- Composite index for ItemValuesMap joins -- Optimizes: ItemValues JOIN ItemValuesMap ON ItemValues.Id = ItemValuesMap.ItemValueId CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_id_type_cleanvalue ON library."ItemValues" ("Id", "Type", "CleanValue"); -- Index for reverse lookups (find all items with specific values) -- Supports queries like "find all genres" or "find all tags" CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_type_id ON library."ItemValues" ("Type", "Id") WHERE "Type" IS NOT NULL; -- Partial index for common value types (Genre, Tags, Studio, etc.) -- Reduces index size while covering most common queries CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_common_types ON library."ItemValues" ("Type", "CleanValue", "Id") WHERE "Type" IN (0, 1, 2, 3, 4, 5, 6, 7, 8); -- Common metadata types \echo 'ItemValues indexes created successfully!' \echo '' -- ============================================================================ -- 3. UPDATE STATISTICS -- ============================================================================ \echo '3. Updating Table Statistics...' \echo '-----------------------------------------' -- Update statistics so query planner knows about new indexes ANALYZE VERBOSE library."Peoples"; ANALYZE VERBOSE library."ItemValues"; \echo '' \echo '=========================================' \echo 'Optimization Complete!' \echo '=========================================' \echo '' -- ============================================================================ -- 4. VERIFY NEW INDEXES -- ============================================================================ \echo '4. Verifying New Indexes...' \echo '-----------------------------------------' -- Show all indexes on Peoples table \echo '' \echo 'Peoples Table Indexes:' SELECT schemaname, tablename, indexname, pg_size_pretty(pg_relation_size(indexrelid)) AS index_size FROM pg_stat_user_indexes WHERE schemaname = 'library' AND tablename = 'Peoples' ORDER BY indexname; \echo '' \echo 'ItemValues Table Indexes:' -- Show all indexes on ItemValues table SELECT schemaname, tablename, indexname, pg_size_pretty(pg_relation_size(indexrelid)) AS index_size FROM pg_stat_user_indexes WHERE schemaname = 'library' AND tablename = 'ItemValues' ORDER BY indexname; \echo '' \echo '=========================================' \echo 'Next Steps:' \echo '1. Use Jellyfin normally for a few hours' \echo '2. Run: sql\diagnostics.sql' \echo '3. Check if sequential scans decreased' \echo '4. Run: sql\query-analysis.sql for slow query details' \echo '========================================='