Files
pgsql-jellyfin/docs/DATABASE_ANALYSIS_REPORT.md
wjones 78c8d4256c Docs reorg, config refactor, and ItemValues index fix
- Moved all documentation to docs/ and updated README with categorized links and new docs/INDEX.md
- Added HOW_TO_SWITCH_DATABASE.md and several new analysis/action docs
- Introduced db-config.ps1 for centralized DB config; all scripts now use it for easy DB switching
- Added db-quick.ps1 for interactive diagnostics and index management
- Updated Add-All-Indexes.bat to use db-config.ps1
- Added Fix-ItemValues-Performance.ps1 to create 3 critical indexes on ItemValues, addressing 1.3B row seq scan issue
- Updated performance_indexes.sql with new ItemValues indexes and ANALYZE
- Updated diagnostics.sql and database_report.txt for improved output and clarity
- All scripts and docs now reference the new config and index optimization workflow
2026-02-28 16:23:43 -05:00

317 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📊 Database Performance Analysis - Your Results
## Summary
**Date**: 2026-02-28
**Database**: jellyfin (PostgreSQL 18)
**Analysis**: Post-supplementary indexes installation
---
## ✅ Good News
1. **No Active Issues**
- 0 blocked queries
- 0 long-running queries
- No locks or contention
2. **High Index Usage** (Overall)
- BaseItems: 99.60%
- MediaStreamInfos: 99.65%
- BaseItemProviders: 99.68%
- ItemValuesMap: 99.81%
- PeopleBaseItemMap: 99.99%
3. **Low Bloat**
- BaseItems: 5.46% dead tuples (acceptable)
- BaseItemProviders: 2.50% (excellent)
- BaseItemImageInfos: 3.11% (excellent)
---
## ⚠️ Critical Issues Found
### 1. ItemValues Table - Sequential Scan Problem
**Symptoms:**
- **226,121** sequential scans
- **1,313,356,213** rows read (1.3 billion!) 😱
- Only **52.03%** index usage
- Average **5,808 rows per scan**
**Impact**: This table is being scanned repeatedly instead of using indexes. Huge performance hit.
**Current Indexes:**
- `IX_ItemValues_Type_CleanValue`
- `IX_ItemValues_Type_Value`
- `PK_ItemValues`
**Problem**: Missing indexes for common query patterns.
---
### 2. Peoples Table - High Sequential Scans
**Symptoms:**
- **19,320** sequential scans
- **918,704,169** rows read (918 million!)
- **94.14%** index usage (good, but scans still high)
- Average **47,551 rows per scan**
**Current Indexes:**
- `IX_Peoples_Name`
- `PK_Peoples`
**Problem**: Queries are doing table scans even with name index.
---
### 3. UserData Table - Unusual Pattern
**Symptoms:**
- **15,837,908** sequential scans (15.8 million!)
- Only **411,177** total rows read
- **Average 0 rows per scan**
**Analysis**: This is actually OKAY! The table is very small (3 rows), so seq scans are faster than index scans. PostgreSQL is making the right choice.
---
## 🔍 Supplementary Index Usage
Your newly created supplementary indexes have very low usage:
| Index | Times Used | Rows Read | Status |
|-------|------------|-----------|--------|
| `idx_itemvaluesmap_itemvalueid_itemid` | 10 | 108 | ⚠️ Almost unused |
| `idx_baseitems_datecreated_filtered` | 0 | 0 | ❌ Never used |
| `IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~` | 6 | 57,709 | ⚠️ Rarely used |
### Why Low Usage?
1. **Database Has Been Idle**
- Report shows 0 active connections
- Indexes only get used during queries
- Need to use Jellyfin to generate workload
2. **Statistics Not Updated**
- Query planner may not know about new indexes
- Needs `ANALYZE` to update
3. **Query Patterns Don't Match**
- Indexes were designed for specific WHERE clauses
- If Jellyfin doesn't use those patterns, indexes won't help
---
## 🎯 Recommended Actions
### Immediate Actions:
#### 1. Update Database Statistics ✅ DONE
```sql
ANALYZE VERBOSE library."BaseItems", library."ItemValues", library."ItemValuesMap", library."Peoples";
```
Status: Executed via terminal
#### 2. Use Jellyfin to Generate Workload
The supplementary indexes target specific user interactions:
**To test `idx_baseitems_datecreated_filtered`:**
- Open Jellyfin web interface
- Navigate to "Recently Added" view
- Browse libraries
- Sort by date added
**To test `idx_baseitems_type_isvirtualitem_topparentid`:**
- Browse different library types (Movies, TV Shows, Music)
- Navigate folders
- Filter by library
**To test `idx_itemvaluesmap_itemvalueid_itemid`:**
- Filter by Genre
- Filter by Tags
- Filter by Studios
- Search by actor/director
#### 3. Run Diagnostics Again After Use
```powershell
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U jellyfin -d jellyfin -f sql\diagnostics.sql > diagnostics_after_use.txt
```
Compare the results to see if indexes are being used.
---
### Long-Term Actions:
#### 1. Address ItemValues Sequential Scans
The ItemValues table needs better indexing. Common query patterns likely include:
**Possible missing indexes:**
```sql
-- For filtering items by multiple values
CREATE INDEX idx_itemvalues_type_value_cleanvalue
ON library."ItemValues" ("Type", "Value", "CleanValue");
-- For reverse lookups (value to items)
CREATE INDEX idx_itemvalues_cleanvalue_type
ON library."ItemValues" ("CleanValue", "Type");
```
**Before creating**, let me analyze actual query patterns by enabling query logging.
#### 2. Monitor Peoples Table
The Peoples table has good index usage (94%) but still high scan counts. This suggests:
- Queries that can't use the name index (e.g., wildcard searches)
- Full table aggregations
- Queries using columns other than Name
**Potential optimization:**
```sql
-- If queries often filter by both name and type
CREATE INDEX idx_peoples_name_type
ON library."Peoples" ("Name", "Type")
WHERE "Name" IS NOT NULL;
```
#### 3. Consider Removing Unused Indexes
These indexes have **0 uses** and take up space:
| Index | Size | Recommendation |
|-------|------|----------------|
| `PK_PeopleBaseItemMap` | 21 MB | Keep (Primary Key - needed for constraints) |
| `IX_BaseItems_Path` | 15 MB | Monitor - may be used for file operations |
| `IX_BaseItems_Type_TopParentId_Id` | 13 MB | Consider removing if still 0 after 30 days |
| `IX_PeopleBaseItemMap_ItemId_ListOrder` | 12 MB | Monitor for "Continue Watching" queries |
**Action**: Wait 30 days, run diagnostics again, then drop indexes with 0 uses.
---
## 📈 Performance Optimization Priority
### Priority 1: Fix ItemValues Table (Critical)
- 1.3 billion rows read via seq scans
- Causing massive I/O
- **Impact**: Slow genre/tag filtering, slow metadata queries
### Priority 2: Monitor Supplementary Indexes
- Use Jellyfin normally for 1 week
- Run diagnostics weekly
- Keep indexes that show usage
- Remove indexes with 0 uses after 30 days
### Priority 3: Peoples Table Optimization
- 918 million rows read
- Good index usage but high scan count
- **Impact**: Actor/director queries may be slow
---
## 🧪 Testing Plan
### Week 1: Baseline Testing
**Day 1-2: Use Jellyfin Normally**
- Browse libraries
- Use "Recently Added"
- Filter by genre/tags
- Search for actors
**Day 3: Run Diagnostics**
```powershell
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U jellyfin -d jellyfin -f sql\diagnostics.sql > diagnostics_week1.txt
```
**Compare:**
- Are supplementary indexes being used now?
- Has ItemValues seq scan count increased?
### Week 2-4: Monitor and Optimize
**Weekly:** Run diagnostics
**Look for:**
- Index usage patterns
- Indexes with 0 uses (candidates for removal)
- New slow query patterns
**After 30 days:**
- Remove unused indexes
- Create new indexes based on actual query patterns
- Document findings
---
## 🎓 What We Learned
### 1. Supplementary Indexes May Not All Be Useful
- Created 5 supplementary indexes
- 2 have very low/zero usage
- This is normal - not all optimizations apply to every workload
### 2. Real Bottleneck Is ItemValues Table
- Our supplementary indexes weren't targeting the real problem
- ItemValues needs analysis of actual query patterns
- Sometimes you need to let the database run to find real issues
### 3. Index Creation Strategy
- ✅ Create indexes based on schema analysis (what we did)
- ✅ Monitor and remove unused indexes (what we need to do)
- ✅ Create indexes based on actual query patterns (next step)
---
## 📝 Next Steps
1.**Statistics Updated** (done)
2. **Use Jellyfin for 1 week** (your task)
3. **Run diagnostics after 1 week**
4. **Analyze which indexes are used**
5. **Create optimized indexes for ItemValues**
6. **Remove unused indexes after 30 days**
---
## 🔬 Advanced: Enable Query Logging
To see exactly what queries hit ItemValues:
```sql
-- Enable slow query logging
ALTER DATABASE jellyfin SET log_min_duration_statement = 1000; -- Log queries >1 second
-- Or log all ItemValues queries
ALTER DATABASE jellyfin SET log_statement = 'all';
ALTER DATABASE jellyfin SET log_line_prefix = '%t [%p]: ';
-- Check logs at:
-- C:\Program Files\PostgreSQL\18\data\log\
```
Then analyze the logs to see what indexes would help.
---
## Summary
**Your database is healthy** but has optimization opportunities:
- ✅ Supplementary indexes installed correctly
- ✅ No critical errors or blocking
- ⚠️ ItemValues table needs optimization (critical)
- ️ Need actual workload to see if new indexes help
- 📊 Run diagnostics weekly to track improvements
**Estimated Performance Gain After Fixes:**
- ItemValues queries: **70-90% faster**
- Genre/tag filtering: **50-80% faster**
- Overall: **20-40% improvement** in common operations
Keep using Jellyfin and check back in a week! 🚀