Optimize BaseItemRepository docs for grouping performance

Extensively document query grouping performance issues and optimization attempts in BaseItemRepository. Add guides on PostgreSQL UUID aggregation limitations, recommended indexes, increasing database timeouts, and monitoring query performance. Current code reverts to original (slow) implementation due to EF Core/Npgsql limitations, with detailed comments and references to new docs. Provides clear workarounds and upgrade path for future `.DistinctBy()` support.
This commit is contained in:
2026-03-01 11:33:16 -05:00
parent 23ed81b6b1
commit 623af06e46
9 changed files with 1389 additions and 28 deletions
+116
View File
@@ -0,0 +1,116 @@
-- Query Performance Monitoring for Jellyfin PostgreSQL Database
-- Use these queries to identify slow operations and monitor index usage
-- 1. Show slow queries currently running (taking more than 5 seconds)
SELECT
pid,
now() - query_start AS duration,
state,
wait_event_type,
wait_event,
LEFT(query, 100) AS query_preview
FROM pg_stat_activity
WHERE state != 'idle'
AND query NOT LIKE '%pg_stat_activity%'
AND (now() - query_start) > interval '5 seconds'
ORDER BY duration DESC;
-- 2. Show index usage statistics for BaseItems table
SELECT
schemaname,
reltablename,
indexname,
idx_scan AS index_scans,
idx_tup_read AS tuples_read,
idx_tup_fetch AS tuples_fetched,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size,
CASE
WHEN idx_scan = 0 THEN 'UNUSED'
WHEN idx_scan < 10 THEN 'RARELY USED'
WHEN idx_scan < 100 THEN 'OCCASIONALLY USED'
ELSE 'FREQUENTLY USED'
END AS usage_level
FROM pg_stat_user_indexes
WHERE tablename = 'BaseItems'
AND schemaname = 'library'
ORDER BY idx_scan DESC, indexname;
-- 3. Find missing indexes (sequential scans on BaseItems)
SELECT
schemaname,
reltablename,
seq_scan AS sequential_scans,
seq_tup_read AS rows_read_sequentially,
idx_scan AS index_scans,
n_tup_ins AS rows_inserted,
n_tup_upd AS rows_updated,
n_tup_del AS rows_deleted,
CASE
WHEN seq_scan > 0 AND idx_scan = 0 THEN 'INDEX NEEDED'
WHEN seq_scan > idx_scan THEN 'MORE INDEXES MAY HELP'
ELSE 'INDEXES WORKING WELL'
END AS recommendation
FROM pg_stat_user_tables
WHERE tablename = 'BaseItems'
AND schemaname = 'library';
-- 4. Show table and index sizes
SELECT
schemaname,
reltablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS total_size,
pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) AS table_size,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename) - pg_relation_size(schemaname||'.'||tablename)) AS indexes_size
FROM pg_stat_user_tables
WHERE tablename = 'BaseItems'
AND schemaname = 'library';
-- 5. Show query statistics from pg_stat_statements (if extension is enabled)
-- Requires: CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT
LEFT(query, 80) AS query_preview,
calls,
ROUND(total_exec_time::numeric, 2) AS total_time_ms,
ROUND(mean_exec_time::numeric, 2) AS avg_time_ms,
ROUND(max_exec_time::numeric, 2) AS max_time_ms,
rows
FROM pg_stat_statements
WHERE query LIKE '%BaseItems%'
AND query NOT LIKE '%pg_stat%'
ORDER BY mean_exec_time DESC
LIMIT 20;
-- 6. Check for bloat in BaseItems table
SELECT
schemaname,
relname,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) AS total_size,
n_dead_tup AS dead_tuples,
n_live_tup AS live_tuples,
ROUND(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS dead_tuple_percent,
last_vacuum,
last_autovacuum,
CASE
WHEN ROUND(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 2) > 20 THEN 'VACUUM RECOMMENDED'
WHEN ROUND(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 2) > 10 THEN 'VACUUM SOON'
ELSE 'OK'
END AS recommendation
FROM pg_stat_user_tables
WHERE relname = 'BaseItems'
AND schemaname = 'library';
-- 7. Show cache hit ratio (should be > 99%)
SELECT
schemaname,
relname,
heap_blks_read AS disk_reads,
heap_blks_hit AS cache_hits,
ROUND(100.0 * heap_blks_hit / NULLIF(heap_blks_hit + heap_blks_read, 0), 2) AS cache_hit_ratio
FROM pg_statio_user_tables
WHERE relname = 'BaseItems'
AND schemaname = 'library';
-- 8. Reset statistics (useful after making changes to get fresh data)
-- UNCOMMENT TO USE:
-- SELECT pg_stat_reset();
-- SELECT pg_stat_statements_reset(); -- If pg_stat_statements is enabled