本質的な問い
SQLite は Postgres を小さくしたものではありません。そもそも道具としての形が違います。データベース全体がディスク上の 1 つのファイルで、アプリケーションは同じプロセス内にリンクされたライブラリ越しにそのファイルを操作します。サーバーもネットワークもユーザー管理もありません。この設計のおかげで、SQLite はある種の用途では圧倒的に強く、別の用途ではまったく向きません。
判断の決め手は「SQLite で速度は足りるか?」ではほぼありません(たいてい足ります)。本当に問うべきは「アプリの 形 が SQLite の得意分野と噛み合っているか?」です。これを左右するのは主に 2 つ。データがどこに置かれるか、そして同時に書き込むものがいくつあるか、です。
SQLite の使いどころ:データがアプリと一緒にある場合
SQLite が真価を発揮するのは、データベースが 1 台のマシン上の 1 つのアプリに紐づいているときです。ファイルはコードのすぐ隣に置かれ、アプリはそれを直接開く。アーキテクチャと呼べるものはそれだけです。
あの数行だけのスキーマで、実際のアプリのバックエンドが丸ごと完結してしまうこともあります。このパターンがしっくりハマる SQLite のユースケースをいくつか挙げてみましょう。
- デスクトップアプリ・モバイルアプリ。iOS や Android で構造化されたローカルストレージを使うアプリは、ほぼ例外なく裏側で SQLite を使っています。Firefox や Chrome をはじめ、主要なブラウザもそうです。
- CLI ツール。
gitやパッケージマネージャ、dotfile マネージャなどは、組み込みデータベースとして SQLite を活用しています。 - 組み込み機器。ルーター、自動車、航空機など、わずか数百キロバイトのフットプリントでデータベースが必要になる場面で重宝されます。
- テストスイート。テストごとにまっさらな SQLite ファイル(あるいは
:memory:データベース)を用意するほうが、Postgres を立ち上げるより速くて分離性も高いです。
データを複数マシン間で共有する必要がないなら、SQLite が正解になるケースがほとんどです。
読み取り中心の Web アプリには SQLite が最適
SQLite は読み取り処理が本当に得意です。同時に大量のリーダーがアクセスしても競合は起こらず、インデックスが効いたクエリならマイクロ秒単位で返ってきます。ブログ、ドキュメントサイト、マーケティングページ、小規模な SaaS ダッシュボードのように、ユーザーがコンテンツを「読む」のがメインのサイトであれば、SQLite で十分にさばけます。むしろネットワーク越しの Postgres よりも、ラウンドトリップが発生しないぶん速いことすらあります。
ただし注意したいのが書き込みです。SQLiteは書き込みを直列化する仕組みになっていて、ロックを保持できるのは常に1つのライターだけ。書き手が数人のブログ程度なら気にもなりませんが、毎秒数千ユーザーがメッセージを投稿するチャットアプリとなると話は別で、ここがボトルネックになります。
このあたりは後ほど解説するWALモード(write-ahead logging)を使うと、リーダーとライターが並行して動けるようになり、上限がぐっと引き上げられます。実際、SQLite + WALの構成で1日数百万リクエストをさばいている本番サイトはいくらでもあります。
ローカルキャッシュや一時データにSQLiteを使う
構造化されたローカルストレージが必要な場面、つまりJSONファイルでは物足りないけど本格的なDBサーバーを立てるほどでもない、そんなときにSQLiteは抜群の選択肢です。
ログ、解析用のバッファ、ETLのステージング、機械学習の特徴量ストア、IDEのインデックス——このあたりはどれもSQLiteの得意分野です。ファイル1つで持ち運べるし、クエリは本物のSQLがそのまま使えるし、サーバーの面倒を見る必要もありません。
SQLiteを避けるべきケース:同時書き込みが多い場合
ここがSQLiteのいちばんハマりどころです。SQLiteはデータベース単位で書き込みロックをかける仕組みなので、書き込みできるのは常に1プロセスだけ。複数のプロセスが同時にINSERTしようとすると、片方は順番待ちになります。
ふつうのアプリではほぼ問題になりません。書き込みは頻度も少ないし、すぐ終わるからです。ただし、ワークロードが次のようなパターンだとちょっと話が変わってきます。
- 何千人ものユーザーが同時に書き込みを行うマルチテナントSaaS
- スループット重視のメッセージキューやイベントログ
- 状態が常に変わり続けるリアルタイムのゲームやチャットのバックエンド
こうしたケースではSQLiteがボトルネックになります。PostgreSQLやMySQLは行単位のロックを採用していて、まさにこういう用途のために設計されたものです。素直にそちらを選びましょう。
-- ライターが溜まったときに表示されるエラー:
Error: database is locked
通常の負荷でこういう症状が出るなら、それはバグを回避する話ではなく、SQLite がそもそも合っていないというサインです。
複数マシンにまたがる用途で SQLite を使わない
SQLite はインプロセス型のライブラリです。アプリケーションがファイルを直接読み書きする仕組みなので、データベースファイルは通常のファイルシステム呼び出し(read() や write())でアクセスできるディスク上に置かれている必要があります。
つまり、次のような構成には向きません。
- ロードバランサーの裏に複数のアプリケーションサーバーを並べて、ひとつのデータベースを共有したいケース。(NFS のようなネットワークファイルシステムは技術的には動きますが、負荷がかかるとファイルが壊れます。やめましょう。)
- サーバーレス関数のように、呼び出しごとに別のマシンで実行される環境。
- 共有データベースが必要な Kubernetes の Pod ── 永続ボリューム付きの単一 Pod 構成にするなら別ですが。
複数マシン上の複数プロセスがデータベースに書き込む構成になっているなら、クライアント・サーバー型のデータベースが必要です。ここが分かれ目です。
データベースレベルのユーザー管理が必要なら SQLite は使わない
SQLite にはユーザー、ロール、権限という概念がありません。データベースは単なるファイルなので、ファイルを読める人は中身を全部読めますし、書ける人は全部書き換えられます。アクセス制御は OS の仕事です。
シングルユーザーのデスクトップアプリなら問題ありません。ただし、データベース_内部_で人ごとに異なる権限を持たせたいマルチテナント型のシステムなら、Postgres や MySQL を選ぶべきです。
判断用チェックリスト
以下を上から順に確認してみてください。すべて「はい」なら、SQLite はおそらく良い選択です。
- データベースがアプリケーションと同じマシン上にある。
- 接続するのは 1 プロセス(あるいは、ほとんどが読み取りの少数プロセス)だけ。
- データ全体が 1 台のディスクに余裕で収まる ── テラバイト級でも構わないが、あくまで 1 台のディスク。
- データベースレベルのユーザー権限管理が不要。
- 同時書き込みは時々発生する程度で、メインのワークロードではない。
ひとつでも「いいえ」があるなら、Postgres や MySQL を検討してください。次の 2 ページでそれぞれと直接比較します。
まとめ
- SQLite が真価を発揮するのは、データベースがアプリケーションと同居しているとき。デスクトップアプリ、モバイル、組み込み、CLI ツール、テストスイート、読み取り中心のサイト、ローカルキャッシュなどです。
- 本番環境でも十分通用します ── 何十億ものデバイスに搭載されている実績があります。制約は品質の問題ではなく、アーキテクチャ上のものです。
- 大量の同時書き込み、複数マシンからのアクセス、ユーザー単位のデータベース権限が必要なら、SQLite は避けましょう。
次は SQLite のインストール
理屈はこのくらいにして、次のページでは SQLite を実際に手元のマシンに用意する手順を見ていきます。macOS とほとんどの Linux ディストリには最初から入っており、Windows でもダウンロード 1 回で済みます。インストール後はコマンドラインから動作確認まで進めます。
よくある質問
SQLiteはどんな場面で使うべき?
アプリケーションとデータが同じ場所にあるケース全般に向いています。デスクトップアプリ、モバイルアプリ、CLIツール、組み込み機器、小〜中規模のWebサイト、ローカルキャッシュ、テスト用DBなどが典型例です。要するに「単一プロセス(または読み取り中心の少数プロセス)から本格的なSQLを使いたいけれど、わざわざサーバーを立てたくない」という状況にぴったりハマります。
SQLiteは本番環境でも使える?
ワークロードの形が合っていれば、十分本番投入できます。実際、iPhoneやAndroid、主要ブラウザにはすべてSQLiteが組み込まれており、本番運用しているWebサイトもたくさんあります。問題は信頼性ではなく同時書き込みです。データベース全体で書き込みは常に1プロセスのみ、しかもDBファイルはアプリと同じマシン上に置く必要があります。
SQLiteを避けたほうがいいのはどんなケース?
同時書き込みが多いケース、複数のアプリサーバーからネットワーク越しにDBへアクセスしたいケース、ユーザー単位で細かい権限管理が必要なケースは避けたほうが無難です。こういった用途はもともとPostgresやMySQLが想定している土俵なので、素直にそちらを使いましょう。