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
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
-- 10_create_supplementary_indexes.sql
|
||||
-- Creates additional performance indexes not included in the base schema dump
|
||||
-- These are safe to run multiple times (uses IF NOT EXISTS checks)
|
||||
|
||||
\echo 'Creating supplementary performance indexes...';
|
||||
|
||||
-- ============================================================================
|
||||
-- BaseItems Supplementary Indexes
|
||||
-- (Schema dump has 19 indexes, adding 3 more for specific query patterns)
|
||||
-- ============================================================================
|
||||
|
||||
-- Composite index for filtered library browsing (type + virtual + parent)
|
||||
-- Use case: Browse items by type in a specific library, excluding virtual items
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'library'
|
||||
AND tablename = 'BaseItems'
|
||||
AND indexname = 'idx_baseitems_type_isvirtualitem_topparentid'
|
||||
) THEN
|
||||
RAISE NOTICE 'Creating idx_baseitems_type_isvirtualitem_topparentid...';
|
||||
CREATE INDEX CONCURRENTLY idx_baseitems_type_isvirtualitem_topparentid
|
||||
ON library."BaseItems" ("Type", "IsVirtualItem", "TopParentId")
|
||||
WHERE "IsVirtualItem" = false;
|
||||
RAISE NOTICE '✓ Created idx_baseitems_type_isvirtualitem_topparentid';
|
||||
ELSE
|
||||
RAISE NOTICE '✓ Index idx_baseitems_type_isvirtualitem_topparentid already exists';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN duplicate_table THEN
|
||||
RAISE NOTICE '✓ Index idx_baseitems_type_isvirtualitem_topparentid already exists (caught duplicate)';
|
||||
END $$;
|
||||
|
||||
-- Index for folder hierarchy queries
|
||||
-- Use case: Navigate folder structures efficiently
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'library'
|
||||
AND tablename = 'BaseItems'
|
||||
AND indexname = 'idx_baseitems_topparentid_isfolder'
|
||||
) THEN
|
||||
RAISE NOTICE 'Creating idx_baseitems_topparentid_isfolder...';
|
||||
CREATE INDEX CONCURRENTLY idx_baseitems_topparentid_isfolder
|
||||
ON library."BaseItems" ("TopParentId", "IsFolder", "IsVirtualItem")
|
||||
WHERE "TopParentId" IS NOT NULL;
|
||||
RAISE NOTICE '✓ Created idx_baseitems_topparentid_isfolder';
|
||||
ELSE
|
||||
RAISE NOTICE '✓ Index idx_baseitems_topparentid_isfolder already exists';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN duplicate_table THEN
|
||||
RAISE NOTICE '✓ Index idx_baseitems_topparentid_isfolder already exists (caught duplicate)';
|
||||
END $$;
|
||||
|
||||
-- Index for recently added content with filters
|
||||
-- Use case: "Recently Added" view across all libraries
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'library'
|
||||
AND tablename = 'BaseItems'
|
||||
AND indexname = 'idx_baseitems_datecreated_filtered'
|
||||
) THEN
|
||||
RAISE NOTICE 'Creating idx_baseitems_datecreated_filtered...';
|
||||
CREATE INDEX CONCURRENTLY idx_baseitems_datecreated_filtered
|
||||
ON library."BaseItems" ("DateCreated" DESC, "Type", "IsVirtualItem")
|
||||
WHERE "DateCreated" IS NOT NULL AND "IsVirtualItem" = false;
|
||||
RAISE NOTICE '✓ Created idx_baseitems_datecreated_filtered';
|
||||
ELSE
|
||||
RAISE NOTICE '✓ Index idx_baseitems_datecreated_filtered already exists';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN duplicate_table THEN
|
||||
RAISE NOTICE '✓ Index idx_baseitems_datecreated_filtered already exists (caught duplicate)';
|
||||
END $$;
|
||||
|
||||
-- ============================================================================
|
||||
-- ItemValuesMap Supplementary Index
|
||||
-- (Schema dump has IX_ItemValuesMap_ItemId, adding reverse lookup)
|
||||
-- ============================================================================
|
||||
|
||||
-- Index for reverse lookup (find items by genre/tag)
|
||||
-- Use case: "Show all items with genre 'Action'"
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'library'
|
||||
AND tablename = 'ItemValuesMap'
|
||||
AND indexname = 'idx_itemvaluesmap_itemvalueid_itemid'
|
||||
) THEN
|
||||
RAISE NOTICE 'Creating idx_itemvaluesmap_itemvalueid_itemid...';
|
||||
CREATE INDEX CONCURRENTLY idx_itemvaluesmap_itemvalueid_itemid
|
||||
ON library."ItemValuesMap" ("ItemValueId", "ItemId");
|
||||
RAISE NOTICE '✓ Created idx_itemvaluesmap_itemvalueid_itemid';
|
||||
ELSE
|
||||
RAISE NOTICE '✓ Index idx_itemvaluesmap_itemvalueid_itemid already exists';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN duplicate_table THEN
|
||||
RAISE NOTICE '✓ Index idx_itemvaluesmap_itemvalueid_itemid already exists (caught duplicate)';
|
||||
END $$;
|
||||
|
||||
-- ============================================================================
|
||||
-- ActivityLogs Supplementary Index
|
||||
-- (Schema dump has IX_ActivityLogs_DateCreated, adding user-specific index)
|
||||
-- ============================================================================
|
||||
|
||||
-- Index for user-specific activity queries
|
||||
-- Use case: "Show activity for user X"
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Check if ActivityLogs table exists
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = 'activitylog'
|
||||
AND table_name = 'ActivityLogs'
|
||||
) THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_indexes
|
||||
WHERE schemaname = 'activitylog'
|
||||
AND tablename = 'ActivityLogs'
|
||||
AND indexname = 'idx_activitylogs_userid_datecreated'
|
||||
) THEN
|
||||
RAISE NOTICE 'Creating idx_activitylogs_userid_datecreated...';
|
||||
CREATE INDEX CONCURRENTLY idx_activitylogs_userid_datecreated
|
||||
ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC)
|
||||
WHERE "UserId" IS NOT NULL;
|
||||
RAISE NOTICE '✓ Created idx_activitylogs_userid_datecreated';
|
||||
ELSE
|
||||
RAISE NOTICE '✓ Index idx_activitylogs_userid_datecreated already exists';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE '⚠ ActivityLogs table not found, skipping user-specific index';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN duplicate_table THEN
|
||||
RAISE NOTICE '✓ Index idx_activitylogs_userid_datecreated already exists (caught duplicate)';
|
||||
END $$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Analyze Tables to Update Statistics
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Updating table statistics...';
|
||||
|
||||
ANALYZE library."BaseItems";
|
||||
ANALYZE library."ItemValuesMap";
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = 'activitylog'
|
||||
AND table_name = 'ActivityLogs'
|
||||
) THEN
|
||||
ANALYZE activitylog."ActivityLogs";
|
||||
RAISE NOTICE '✓ ActivityLogs statistics updated';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
\echo '✓ Supplementary indexes created successfully!';
|
||||
\echo '';
|
||||
\echo 'Summary:';
|
||||
\echo ' - Added 3 composite indexes on BaseItems';
|
||||
\echo ' - Added 1 reverse lookup index on ItemValuesMap';
|
||||
\echo ' - Added 1 user-specific index on ActivityLogs';
|
||||
\echo '';
|
||||
\echo 'These indexes complement the 50+ existing indexes from your schema dump.';
|
||||
Reference in New Issue
Block a user