はじめに
SQLite3 のメンテナンスを C# アプリケーションの起動時に実施する備忘録です。
改訂履歴
- 2026/08/14 : 初版公開。
本文
1. 環境
- .NET 8.0
- Microsoft.Data.Sqlite.Core 10.0.11
- SQLite3 3.53.3
- SQLitePCLRaw.bundle_e_sqlite3 2.1.12
- Visual Studio Community 2022
2. 実装
SQLiteManager クラスに Backup() と MaintenanceAsync(bool isSimple) を実装しました。Backup() の方は Microsoft.Data.Sqlite.SqliteConnection に async でバックアップできるメソッドがなかったので、同期処理になっています。
SQLiteManager.cs
using System.IO;
using Microsoft.Data.Sqlite;
namespace SQLiteMaintenanceExample;
/// <summary>
/// SQLite データベースの管理を行います。
/// </summary>
public static class SQLiteManager
{
private static readonly string s_connectionString = "Data Source=DataBase.sqlite";
/// <summary>
/// バックアップを行います。
/// </summary>
/// <returns>バックアップに成功した場合は <see langword="true"/>、それ以外の場合は <see langword="false"/>。</returns>
public static bool Backup()
{
try
{
// exe と同じ場所に backup フォルダを作成する。
var backupDirectory = Path.Combine(AppContext.BaseDirectory, "backup");
Directory.CreateDirectory(backupDirectory);
// バックアップファイル名を作成する。
var fileName = $"DataBase_{DateTime.Now:yyyyMMdd_HHmmss}.sqlite";
var backupPath = Path.Combine(backupDirectory, fileName);
// 接続する。
using var source = new SqliteConnection(s_connectionString);
source.Open();
// バックアップ先の接続文字列を作成する。
var bkConnStringBuilder = new SqliteConnectionStringBuilder
{
DataSource = backupPath
};
// バックアップを行う。
using var destination = new SqliteConnection(bkConnStringBuilder.ToString());
destination.Open();
source.BackupDatabase(destination);
return true;
}
catch
{
// ※必要に応じて異常処理を実装してください。
return false;
}
}
/// <summary>
/// メンテナンスを非同期で行います。
/// </summary>
/// <param name="isSimple">簡易メンテナンスかどうかを示す値。</param>
/// <returns>非同期操作を表すタスク。メンテナンスに成功した場合は <see langword="true"/>、それ以外の場合は <see langword="false"/>。</returns>
public static async Task<bool> MaintenanceAsync(bool isSimple)
{
try
{
await using var connection = new SqliteConnection(s_connectionString);
await connection.OpenAsync();
// DB 破損チェック。
await using (SqliteCommand cmd = connection.CreateCommand())
{
cmd.CommandText = isSimple
? "PRAGMA quick_check;"
: "PRAGMA integrity_check;";
var result = (await cmd.ExecuteScalarAsync())?.ToString();
if (!string.Equals(result, "ok", StringComparison.Ordinal))
{
// ※必要に応じて異常処理を実装してください。
return false;
}
}
// インデックスの再構築。
if (!isSimple)
{
await using SqliteCommand cmd = connection.CreateCommand();
cmd.CommandText = "REINDEX;";
await cmd.ExecuteNonQueryAsync();
}
// 統計情報の更新。
if (!isSimple)
{
// PRAGMA optimize を実行するなら ANALYZE は不要なはずだが
// 念のため、明示的に実行しておく。
await using SqliteCommand cmd = connection.CreateCommand();
cmd.CommandText = "ANALYZE;";
await cmd.ExecuteNonQueryAsync();
}
// DB 最適化。
await using (SqliteCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "PRAGMA optimize;";
await cmd.ExecuteNonQueryAsync();
}
// WAL ファイルの整理。
await using (SqliteCommand cmd = connection.CreateCommand())
{
// WAL モードの場合、WAL ファイルを整理して小さくする。
cmd.CommandText = "PRAGMA journal_mode;";
var journalMode = (await cmd.ExecuteScalarAsync())?.ToString();
if (string.Equals(journalMode, "wal", StringComparison.OrdinalIgnoreCase))
{
cmd.CommandText = "PRAGMA wal_checkpoint(TRUNCATE);";
await cmd.ExecuteNonQueryAsync();
}
}
// DB 圧縮。
await using (SqliteCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "VACUUM;";
await cmd.ExecuteNonQueryAsync();
}
return true;
}
catch
{
// ※必要に応じて異常処理を実装してください。
return false;
}
}
}
3. 使用例
WPF アプリケーションでの使用例です。
App.xaml.cs
using System.Windows;
namespace SQLiteMaintenanceExample;
/// <summary>
/// Windows Presentation Foundation アプリケーションを表します。
/// </summary>
public partial class App : Application
{
// 必要に応じて取得処理を実装してください。
private static readonly bool s_isSimpleMaintenance = false;
/// <summary>
/// <see cref="Application.Startup"/> イベントを処理します。
/// </summary>
/// <param name="e">イベントデータを含む <see cref="StartupEventArgs"/>。</param>
protected override async void OnStartup(StartupEventArgs e)
{
// バックアップを実行する。
if (!SQLiteManager.Backup())
{
// ※必要に応じて異常処理を実装してください。
MessageBox.Show("Failed to backup the database.");
}
// メンテナンスを実行する。
if (!await SQLiteManager.MaintenanceAsync(s_isSimpleMaintenance))
{
// ※必要に応じて異常処理を実装してください。
MessageBox.Show("Failed to maintain the database.");
}
// メインウィンドウを表示する。
var mainWindow = new MainWindow();
MainWindow = mainWindow;
mainWindow.Show();
}
}
おわりに
DB は、パフォーマンスが低下してからが本番です。