りおんクロニクル


SQLite × キャッシュ戦略|体感速度を劇的に上げる高速化テクニック【2026年版】

Home【2026年版】C# / .NET入門と実践ガイド|基礎・業務アプリ開発・SQLite連携まで体系的に解説

SQLiteは軽量で高速ですが、設計次第で「爆速」にも「もっさり」にもなるデータベースです。 特に業務アプリでは、ユーザーが毎日触る画面ほど体感速度が重要になります。

この記事では、SQLiteを使ったアプリで 体感速度を劇的に上げるキャッシュ戦略を、実務目線で整理します。

この記事でわかること
・SQLiteでキャッシュが必要になる理由
・メモリキャッシュ(Dictionary / MemoryCache)
・結果キャッシュ(クエリ結果の再利用)
・読み取り専用キャッシュDB(サブDB)
・APIレスポンスキャッシュ × SQLite
・WPF/MVVMとの組み合わせパターン
・業務アプリ向けベストプラクティス

1. なぜSQLiteでもキャッシュが必要になるのか?

SQLiteは速いとはいえ、次のようなケースでは体感的に遅く感じることがあります。

こうした「何度も同じデータを読む」パターンに対して、 キャッシュ戦略を入れると体感速度が一気に変わります。

2. キャッシュ戦略の全体像

SQLite × 業務アプリで使えるキャッシュは大きく4種類あります。

  1. メモリキャッシュ(アプリ内メモリ)
  2. 結果キャッシュ(クエリ結果の再利用)
  3. 読み取り専用キャッシュDB(サブSQLite)
  4. APIレスポンスキャッシュ(サーバー側 or クライアント側)

これらを組み合わせることで、DBアクセス回数を減らし、体感速度を最大化できます。

3. メモリキャッシュ(アプリ内メモリ)

最もシンプルで効果が高いのが、メモリ上にマスタや設定を保持する方法です。

■ 典型的な対象

■ シンプルなDictionaryキャッシュ

public class MasterCache
{
    private readonly IConnectionFactory _factory;
    private Dictionary<int, string> _statusCache = new();

    public MasterCache(IConnectionFactory factory)
    {
        _factory = factory;
    }

    public async Task<string?> GetStatusNameAsync(int statusId)
    {
        if (_statusCache.TryGetValue(statusId, out var name))
            return name;

        using var con = _factory.CreateConnection();
        var sql = "SELECT Name FROM Statuses WHERE Id=@id";
        name = await con.ExecuteScalarAsync<string?>(sql, new { id = statusId });

        if (name != null)
            _statusCache[statusId] = name;

        return name;
    }
}

一度取得したら、以降はメモリから即返却されます。

4. 結果キャッシュ(クエリ結果の再利用)

「同じ検索条件で何度も検索される」画面では、 クエリ結果そのものをキャッシュすると効果的です。

■ キーを工夫する

■ シンプルな結果キャッシュ例

public class QueryCache<T>
{
    private readonly Dictionary<string, List<T>> _cache = new();

    public bool TryGet(string key, out List<T> value)
        => _cache.TryGetValue(key, out value!);

    public void Set(string key, List<T> value)
        => _cache[key] = value;
}

DataGridの再表示やタブ切り替え時に、DBアクセスなしで即座に表示できます。

5. 読み取り専用キャッシュDB(サブSQLite)

「参照専用の重いデータ」を別のSQLiteファイルに切り出し、 読み取り専用キャッシュDBとして扱う方法もあります。

■ 典型的な対象

■ メリット

アプリ起動時にキャッシュDBを更新(再生成)する構成も有効です。

6. APIレスポンスキャッシュ × SQLite

サーバー側にAPIがある場合、 APIレスポンスをSQLiteにキャッシュすることで、 ネットワーク遅延を隠すことができます。

■ クライアント側キャッシュの流れ

  1. API呼び出し前にローカルSQLiteをチェック
  2. キャッシュがあれば即返却
  3. バックグラウンドでAPIを叩いて更新

■ キャッシュテーブル例

CREATE TABLE ApiCache (
    Key TEXT PRIMARY KEY,
    Json TEXT NOT NULL,
    UpdatedAt TEXT NOT NULL
);

Key に URL + クエリ文字列を入れておくと汎用的に使えます。

7. WPF/MVVMとの組み合わせパターン

WPF/MVVMでは、キャッシュをサービス層 or Repository層に閉じ込めると綺麗にまとまります。

■ ViewModel側は「キャッシュの存在を知らない」構造

public class UserListViewModel
{
    private readonly IUserService _service;

    public ObservableCollection<UserDto> Users { get; } = new();

    public async Task LoadAsync()
    {
        var list = await _service.GetUsersAsync(); // 中でキャッシュ利用
        Users.Clear();
        foreach (var u in list)
            Users.Add(u);
    }
}

キャッシュの有無・更新タイミングはすべて サービス層で制御するのがポイントです。

8. キャッシュの「無効化戦略」も必ず決めておく

キャッシュは速くなる代わりに「古くなる」というリスクがあります。 そのため、必ず「いつ捨てるか」を決めておきます。

■ よくある無効化ルール

9. 業務アプリ向けベストプラクティス

まとめ:SQLite × キャッシュ戦略は“体感速度”を決める最後の一手

「クエリはそこそこ速いのに、アプリが重く感じる」 そんなときこそ、キャッシュ戦略の出番です。 この記事をベースに、あなたのアプリに最適な高速化パターンを設計してみてください。

前のページ  次のページ