Fix database initialization detection - check for TABLES not just schemas

This commit is contained in:
2026-03-08 11:07:16 -04:00
parent ac1c2c6c82
commit 7657caa960
4 changed files with 275 additions and 10 deletions
+81
View File
@@ -0,0 +1,81 @@
yes-- Jellyfin index cleanup plan (conservative, phased)
-- Generated: 2026-03-08
-- Notes:
-- 1) This script does NOT run automatically; execute sections manually.
-- 2) Use DROP INDEX CONCURRENTLY to avoid long blocking.
-- 3) Do not run inside an explicit transaction block.
-- 4) Re-check stats after each phase before continuing.
/* -------------------------------------------------------------------------
Baseline: capture current index usage before any change
--------------------------------------------------------------------------- */
SELECT
now() AS captured_at,
schemaname,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname IN ('library', 'authentication', 'users', 'activitylog', 'displaypreferences')
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
/* -------------------------------------------------------------------------
Phase 1 (lowest risk): redundant MediaStreamInfos non-unique indexes
Rationale: all 0 scans since last stats reset, strong overlap among keys.
--------------------------------------------------------------------------- */
-- Run one statement at a time and observe workload/latency between statements.
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType_Language";
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType";
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex";
/* -------------------------------------------------------------------------
Verification checkpoint after Phase 1
--------------------------------------------------------------------------- */
SELECT
now() AS check_time,
schemaname,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
/* -------------------------------------------------------------------------
Phase 2 (medium risk): overlapping BaseItemProviders helper indexes
Rationale: all 0 scans since last stats reset; candidates may be redundant
with PK and alternative access paths, but monitor query plans after each.
--------------------------------------------------------------------------- */
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providerid_idx;
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providervalue_idx;
-- Optional in Phase 2b (only if workload remains healthy after Phase 2):
-- DROP INDEX CONCURRENTLY IF EXISTS library."IX_BaseItemProviders_ProviderId_ProviderValue_ItemId";
/* -------------------------------------------------------------------------
Final review query: confirm remaining low-scan indexes
--------------------------------------------------------------------------- */
SELECT
schemaname,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size,
pg_get_indexdef(indexrelid) AS index_definition
FROM pg_stat_user_indexes
WHERE schemaname IN ('library', 'authentication', 'users', 'activitylog', 'displaypreferences')
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
/* -------------------------------------------------------------------------
Explicitly excluded from removal in this plan:
- Unique and PK-backed indexes (constraint critical)
- IX_Users_Username
- IX_DeviceOptions_DeviceId
--------------------------------------------------------------------------- */
@@ -0,0 +1,183 @@
-- Jellyfin strict index-removal runbook
-- Strategy: exactly ONE DROP per maintenance window.
-- Generated: 2026-03-08
--
-- Important:
-- 1) Execute only one window per maintenance period.
-- 2) Keep each statement standalone (no BEGIN/COMMIT around CONCURRENTLY).
-- 3) If regression appears, run that window's rollback CREATE INDEX CONCURRENTLY.
/* =====================================================================
Shared baseline (run before each window)
===================================================================== */
SELECT
now() AS captured_at,
schemaname,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname IN ('library', 'authentication', 'users', 'activitylog', 'displaypreferences')
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
/* =====================================================================
WINDOW 1 (lowest risk first)
Target: library.IX_MediaStreamInfos_StreamIndex_StreamType_Language
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType_Language";
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex_StreamType_Language"
ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType", "Language");
/* =====================================================================
WINDOW 2
Target: library.IX_MediaStreamInfos_StreamIndex_StreamType
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex_StreamType";
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex_StreamType"
ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType");
/* =====================================================================
WINDOW 3
Target: library.IX_MediaStreamInfos_StreamIndex
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_MediaStreamInfos_StreamIndex";
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'MediaStreamInfos'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_MediaStreamInfos_StreamIndex"
ON library."MediaStreamInfos" USING btree ("StreamIndex");
/* =====================================================================
WINDOW 4 (medium risk)
Target: library.baseitemproviders_providerid_idx
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providerid_idx;
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY baseitemproviders_providerid_idx
ON library."BaseItemProviders" USING btree ("ProviderId", "ItemId");
/* =====================================================================
WINDOW 5 (medium risk)
Target: library.baseitemproviders_providervalue_idx
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library.baseitemproviders_providervalue_idx;
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY baseitemproviders_providervalue_idx
ON library."BaseItemProviders" USING btree ("ProviderValue", "ProviderId");
/* =====================================================================
WINDOW 6 (highest risk among current candidates; keep for last)
Target: library.IX_BaseItemProviders_ProviderId_ProviderValue_ItemId
===================================================================== */
-- Drop:
DROP INDEX CONCURRENTLY IF EXISTS library."IX_BaseItemProviders_ProviderId_ProviderValue_ItemId";
-- Verify impact:
SELECT
now() AS check_time,
relname AS table_name,
indexrelname AS index_name,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'library'
AND relname = 'BaseItemProviders'
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;
-- Rollback (recreate):
CREATE INDEX CONCURRENTLY "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId"
ON library."BaseItemProviders" USING btree ("ProviderId", "ProviderValue", "ItemId");
/* =====================================================================
Explicit exclusions (do not remove in this runbook)
=====================================================================
- Any PK_* index
- Any UNIQUE index enforcing constraints
- users.IX_Users_Username
- authentication.IX_DeviceOptions_DeviceId
===================================================================== */