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
+174
View File
@@ -0,0 +1,174 @@
# Increasing Database Command Timeout
## Problem
Slow queries may timeout after 30 seconds (the default PostgreSQL command timeout), causing errors like:
```
Failed executing DbCommand ("30,024"ms) ... CommandTimeout='30'
```
## Solution
The command timeout is configured in the PostgreSQL connection string, which is built from the database configuration file.
### Step 1: Locate Database Configuration
The database configuration is stored in:
```
<ConfigDir>/database.json
```
For example:
- Linux: `/etc/jellyfin/database.json`
- Windows: `C:/ProgramData/jellyfin/config/database.json`
### Step 2: Add Command Timeout Option
Edit `database.json` and add the `command-timeout` option:
```json
{
"DatabaseType": "Jellyfin-PostgreSQL",
"LockingBehavior": "NoLock",
"CustomProviderOptions": {
"Options": [
{
"Key": "host",
"Value": "localhost"
},
{
"Key": "port",
"Value": "5432"
},
{
"Key": "database",
"Value": "jellyfin"
},
{
"Key": "username",
"Value": "jellyfin"
},
{
"Key": "password",
"Value": "your_password_here"
},
{
"Key": "command-timeout",
"Value": "120"
}
]
}
}
```
### Available Timeout Options
| Option | Default | Unit | Description |
|--------|---------|------|-------------|
| `command-timeout` | 30 | seconds | Maximum time for a query to execute |
| `connection-timeout` | 15 | seconds | Maximum time to establish connection |
### Recommended Values
**For Development/Testing:**
```json
{
"Key": "command-timeout",
"Value": "120"
}
```
- Allows up to 2 minutes for complex queries
- Good for debugging slow queries
**For Production:**
```json
{
"Key": "command-timeout",
"Value": "60"
}
```
- Balances between allowing reasonable query time and failing fast on problems
- Prevents hanging connections
### Step 3: Restart Jellyfin
```bash
# Linux (systemd)
sudo systemctl restart jellyfin
# Or if running manually
# Stop Jellyfin and restart
```
### Step 4: Verify Configuration
Check the logs on startup to see the applied timeout:
```
[INF] PostgreSQL connection: Host=localhost, Port=5432, ...
```
The command timeout is applied to all database commands. You can verify it's working by checking slow query logs:
```
[ERR] Failed executing DbCommand ("45,123"ms) ... CommandTimeout='120'
```
## Alternative: Set via Connection String Directly
If you're configuring PostgreSQL via connection string (advanced), you can set it there:
```
Host=localhost;Database=jellyfin;Username=jellyfin;Password=***;Command Timeout=120;
```
## When to Increase Timeout
**Increase timeout if:**
- Queries are legitimately slow due to large datasets
- You're running complex analytics or reporting queries
- Temporary workaround while optimizing queries
**Don't increase timeout if:**
- Queries should be fast but aren't (fix the query instead)
- Most queries complete quickly (one slow query affects all)
- Timeout masks underlying performance issues
## Better Solutions
Instead of just increasing timeout, consider:
1. **Add Database Indexes** (see `sql/add-performance-indexes.sql`)
2. **Optimize Query Logic** (see `docs/query-grouping-current-status.md`)
3. **Use Application-Level Filtering** (avoid grouping in database)
4. **Upgrade EF Core** (when using stable .NET version)
## Monitoring
After changing timeout, monitor query performance:
```sql
-- Run on PostgreSQL to see slow queries
SELECT
pid,
now() - query_start AS duration,
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;
```
See `sql/monitor-query-performance.sql` for comprehensive monitoring queries.
## Current Query Performance Issue
The grouping queries in `BaseItemRepository.ApplyGroupingFilter` currently generate correlated subqueries that can be slow. Until EF Core translation improves, the options are:
1. **Increase timeout** (this guide)
2. **Add indexes** (`sql/add-performance-indexes.sql`)
3. **Disable grouping** (application-level fix)
See `docs/query-grouping-current-status.md` for full details and all workaround options.