Files
pgsql-jellyfin/sql/performance_indexes.sql
T
wjones 5565dc3e05 Add automated PostgreSQL performance index management
- Add scripts and SQL for base and supplementary indexes (total 23)
- Integrate index checks and auto-creation into Jellyfin startup
- Update csproj to include SQL files in build/publish output
- Add diagnostics, publish/copy scripts, and troubleshooting docs
- Provide detailed guides for migration, verification, and merging
- Ensures robust, automated, and well-documented index setup
2026-02-28 15:13:04 -05:00

202 lines
7.6 KiB
SQL

-- PostgreSQL Performance Indexes for Jellyfin
-- Run this script to improve query performance
-- Safe to run multiple times (uses IF NOT EXISTS)
\timing on
\echo 'Creating performance indexes for Jellyfin PostgreSQL database...'
-- ============================================================================
-- BaseItems Table Indexes
-- ============================================================================
\echo 'Creating indexes on BaseItems table...'
-- Index for filtering by type and virtual items (improves library filtering)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_type_isvirtual
ON library."BaseItems" (Type, BaseItems.IsVirtualItem)
WHERE IsVirtualItem = false;
-- Index for parent-child relationships (improves hierarchy queries)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_parent_type
ON library."BaseItems" (BaseItems.ParentId, Type)
WHERE ParentId IS NOT NULL;
-- Index for date-based queries (recently added items, sorting)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_datecreated
ON library."BaseItems" (BaseItems.DateCreated DESC)
WHERE DateCreated IS NOT NULL;
-- Index for date modified (sync operations)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_datemodified
ON library."BaseItems" (BaseItems.DateModified DESC)
WHERE DateModified IS NOT NULL;
-- Index for sorting by name (alphabetical browsing)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_sortname
ON library."BaseItems" (BaseItems.SortName)
WHERE SortName IS NOT NULL;
-- Index for TopParent lookups (library organization)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_topparent_type
ON library."BaseItems" (BaseItems.TopParentId, Type)
WHERE TopParentId IS NOT NULL;
-- Index for premiere date (upcoming/recent content)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_premieredate
ON library."BaseItems" (BaseItems.PremiereDate DESC)
WHERE PremiereDate IS NOT NULL;
-- Index for production year (decade/year filtering)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_productionyear
ON library."BaseItems" (BaseItems.ProductionYear DESC)
WHERE ProductionYear IS NOT NULL;
-- Index for community rating (sorting by rating)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_rating
ON library."BaseItems" (BaseItems.CommunityRating DESC NULLS LAST);
-- Index for series episodes
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_series_episode
ON library."BaseItems" (BaseItems.SeriesPresentationUniqueKey, BaseItems.IndexNumber, BaseItems.ParentIndexNumber)
WHERE Type = 'MediaBrowser.Controller.Entities.TV.Episode';
-- ============================================================================
-- BaseItemProviders Table Indexes
-- ============================================================================
\echo 'Creating indexes on BaseItemProviders table...'
-- Index for provider value lookups (IMDb, TMDB, etc.)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitem_providers_value
ON library."BaseItemProviders" (ProviderValue, ProviderId);
-- Index for finding all items by provider (reverse lookup)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitem_providers_id
ON library."BaseItemProviders" (ProviderId, ItemId);
-- ============================================================================
-- UserData Table Indexes
-- ============================================================================
\echo 'Creating indexes on UserData table...'
-- Index for finding user's watched items
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_user_played
ON library."UserData" (UserId, Played);
-- Index for finding user's favorite items
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_user_favorite
ON library."UserData" (UserId, IsFavorite)
WHERE IsFavorite = true;
-- Index for last played date
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_lastplayed
ON library."UserData" (LastPlayedDate DESC)
WHERE LastPlayedDate IS NOT NULL;
-- ============================================================================
-- PeopleBaseItemMap Table Indexes
-- ============================================================================
\echo 'Creating indexes on PeopleBaseItemMap table...'
-- Index for finding all items for a person
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_people_items_person
ON library."PeopleBaseItemMap" (PeopleId, ItemId);
-- Index for finding all people for an item (already covered by FK, but explicit)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_people_items_item
ON library."PeopleBaseItemMap" (ItemId, PeopleId);
-- ============================================================================
-- ItemValuesMap Table Indexes
-- ============================================================================
\echo 'Creating indexes on ItemValuesMap table...'
-- Index for finding items by value (genres, tags, etc.)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_map_value
ON library."ItemValuesMap" (ItemValueId, ItemId);
-- ============================================================================
-- ActivityLog Table Indexes
-- ============================================================================
\echo 'Creating indexes on ActivityLog table...'
-- Index for date filtering (recent activity)
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylog_date
ON activitylog."ActivityLog" (DateCreated DESC);
-- Index for user activity
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylog_user
ON activitylog."ActivityLog" (UserId, DateCreated DESC)
WHERE UserId IS NOT NULL;
-- ============================================================================
-- MediaStreamInfos Table Indexes
-- ============================================================================
\echo 'Creating indexes on MediaStreamInfos table...'
-- Index for finding streams by item and type
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_mediastreams_item_type
ON library."MediaStreamInfos" (ItemId, Type);
-- Index for codec searches
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_mediastreams_codec
ON library."MediaStreamInfos" (Codec)
WHERE Codec IS NOT NULL;
-- ============================================================================
-- Analyze Tables
-- ============================================================================
\echo 'Analyzing tables to update statistics...'
ANALYZE library."BaseItems";
ANALYZE library."BaseItemProviders";
ANALYZE library."UserData";
ANALYZE library."PeopleBaseItemMap";
ANALYZE library."ItemValuesMap";
ANALYZE library."MediaStreamInfos";
-- Analyze ActivityLog if it exists
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = 'activitylog'
AND table_name = 'ActivityLog'
) THEN
ANALYZE activitylog."ActivityLog";
RAISE NOTICE 'ActivityLog analyzed';
END IF;
END $$;
-- ============================================================================
-- Report Index Usage
-- ============================================================================
\echo 'Current index usage statistics:'
SELECT
schemaname,
relname as tablename,
indexrelname as indexname,
pg_size_pretty(pg_relation_size(indexrelid)) as index_size,
idx_scan as times_used,
idx_tup_read as rows_read,
idx_tup_fetch as rows_fetched
FROM pg_stat_user_indexes
WHERE schemaname IN ('library', 'activitylog', 'users', 'authentication', 'displaypreferences')
ORDER BY schemaname, relname, indexrelname;
\echo ''
\echo 'Index creation complete!'
\echo ''
\echo 'Note: CONCURRENTLY builds indexes without blocking writes, but takes longer.'
\echo 'Monitor progress with: SELECT * FROM pg_stat_progress_create_index;'
\echo ''
\echo 'After indexing, restart Jellyfin to clear connection pools.'