From 2353f005255b86d75b148a6974e2b9c59372a2cd Mon Sep 17 00:00:00 2001 From: Brett Petch Date: Mon, 10 Apr 2023 17:05:41 -0400 Subject: [PATCH] overhaul: Optimize DB tasks https://github.com/jellyfin/jellyfin/pull/9044#issuecomment-1377079963 --- .../Tasks/OptimizeDatabaseTask.cs | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs index 1f3cb9b63f..4c98e940f9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { - _logger.LogInformation("Optimizing and vacuuming jellyfin.db..."); + _logger.LogInformation("Performing quick maintanance on jellyfin.db."); try { @@ -81,9 +81,100 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks { if (context.Database.IsSqlite()) { + await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(RESTART)", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("PRAGMA quick_check(1)", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("PRAGMA analysis_limit=1024", cancellationToken).ConfigureAwait(false); await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("REINDEX", cancellationToken).ConfigureAwait(false); + _logger.LogInformation("Quick jellyfin.db optimization complete!"); + } + else + { + _logger.LogInformation("This database doesn't support optimization"); + } + } + } + catch (Exception e) + { + _logger.LogError(e, "Error while doing quick jellyfin.db optimization"); + } + } + } + public class OptimizeWeeklyDatabaseTask : IScheduledTask, IConfigurableScheduledTask + { + private readonly ILogger _logger; + private readonly ILocalizationManager _localization; + private readonly IDbContextFactory _provider; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The localization manager. + /// The jellyfin DB context provider. + public OptimizeWeeklyDatabaseTask( + ILogger logger, + ILocalizationManager localization, + IDbContextFactory provider) + { + _logger = logger; + _localization = localization; + _provider = provider; + } + + /// + public string Name => _localization.GetLocalizedString("TaskExtendedOptimizeDatabase"); + + /// + public string Description => _localization.GetLocalizedString("TaskExtendedOptimizeDatabaseDescription"); + + /// + public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory"); + + /// + public string Key => "OptimizeWeeklyDatabaseTask"; + + /// + public bool IsHidden => false; + + /// + public bool IsEnabled => true; + + /// + public bool IsLogged => true; + + /// + /// Creates the triggers that define when the task will run. + /// + /// IEnumerable{BaseTaskTrigger}. + public IEnumerable GetDefaultTriggers() + { + return new[] + { + // Every so often + new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(168).Ticks } + }; + } + + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + _logger.LogInformation("Performing extended maintanance on jellyfin.db."); + + try + { + var context = await _provider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (context.ConfigureAwait(false)) + { + if (context.Database.IsSqlite()) + { await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false); - _logger.LogInformation("jellyfin.db optimized successfully!"); + await context.Database.ExecuteSqlRawAsync("PRAGMA integrity_check(1)", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("PRAGMA foreign_key_check", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("PRAGMA analysis_limit=0", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false); + await context.Database.ExecuteSqlRawAsync("REINDEX", cancellationToken).ConfigureAwait(false); + _logger.LogInformation("Extended jellyfin.db optimization task complete!"); } else { @@ -93,7 +184,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (Exception e) { - _logger.LogError(e, "Error while optimizing jellyfin.db"); + _logger.LogError(e, "Error while performing extended jellyfin.db optimization"); } } }