こんにちは、かつコーチです。
SQLite編もいよいよ最終回です。
これまでファイルベースの仕組み、型アフィニティ、トランザクション、インデックス、WALモード、バックアップと、SQLite固有の特徴を一通り解説してきました。
最終回となる今回は、これらの知識を踏まえて「SQLiteは結局どんなアプリに向いているのか」を、MySQL・PostgreSQLと比較しながら検証していきます。
3つのDBの前提の違い
アーキテクチャの根本的な違いをおさらい
比較の前に、これまでの記事で解説してきたSQLiteの特徴を振り返ります。
| 項目 | SQLite | MySQL | PostgreSQL |
|---|---|---|---|
| アーキテクチャ | サーバーレス(ファイル1つ) | クライアント・サーバー型 | クライアント・サーバー型 |
| 同時書き込み | 1プロセスのみ(WALモードでも同様) | 多数の同時書き込みに対応 | 多数の同時書き込みに対応 |
| データ型の厳密さ | 型アフィニティ(緩い) | 比較的厳密 | 非常に厳密 |
| ネットワーク越しの利用 | 不可(ファイルアクセスが前提) | 可能 | 可能 |
| セットアップの手間 | ほぼ不要 | サーバー構築・設定が必要 | サーバー構築・設定が必要 |
SQLiteとサーバー型DBの最大の違いは、「複数のクライアントから同時に強く書き込まれる状況」を前提にしているかどうかです。
MySQL・PostgreSQLは最初からその前提で設計されているのに対し、SQLiteは「1つのアプリケーションプロセスが自分のデータを持つ」ことを前提に設計されています。
同時書き込み性能の実測イメージ
第4回・第6回で解説した通り、SQLiteはWALモードを使っても、同時に書き込めるのは常に1プロセスだけです。
対してMySQL・PostgreSQLは、行ロックやMVCC(複数バージョン同時実行制御)によって、多数のクライアントが同時に別々の行を更新できます。
-- SQLite:2つのプロセスが同時にUPDATEしようとすると、片方は待たされる
UPDATE inventory SET stock = stock - 1 WHERE product_id = 100;
-- MySQL/PostgreSQL:行ロックにより、別の行への更新であれば並行して進む
UPDATE inventory SET stock = stock - 1 WHERE product_id = 200;
在庫管理システムのように「多数のユーザーが同時に別々の商品の在庫を更新する」ようなワークロードでは、SQLiteの1プロセス制限がボトルネックになりやすい構造です。
用途別の向き不向き
SQLiteが向いているケース
- モバイル・デスクトップアプリのローカルストレージ:iOSやAndroidの標準的なローカルDBとして広く使われている
- テスト環境・CI環境のDB:サーバー起動が不要なため、テスト実行が高速化する
- 読み取り中心・小規模な社内ツール:数人〜十数人が使う管理画面など、書き込み競合がほぼ発生しない規模
- エッジ・IoTデバイス:常時ネットワークに繋がっていない環境でのローカルデータ保存
- 分析用の一時DB:CSVなどをSQLiteに取り込み、SQLで集計・加工してから捨てる使い方
私自身、個人開発の小規模ツールやプロトタイプでは、まずSQLiteで作り始めることが多いです。
環境構築の手間がなく、思いついたアイデアをすぐに形にできるスピード感は、サーバー型DBにはない大きな利点です。
MySQL・PostgreSQLが向いているケース
- 多数のユーザーが同時アクセスするWebサービス:ECサイト、SNS、業務システムなど書き込み競合が頻発する構成
- 複数のアプリケーションサーバーからの接続が必要な構成:SQLiteはファイルアクセス前提のため、複数台のサーバーから直接共有できない
- 厳密なデータ型チェックや高度な制約が必要なシステム:金融系など、データの整合性が事業リスクに直結する領域
- 大規模データに対する複雑な集計・分析:PostgreSQLはウィンドウ関数やJSON型など高度な機能が充実している
複数のWebサーバーが1つのDBを共有するという、一般的なWebサービスの構成そのものが、実はSQLiteの前提(ファイルへの直接アクセス)と相性が悪いという点は、意外と見落とされがちです。
判断フロー:どちらを選ぶべきか
実際の案件でDBを選ぶ際は、以下の観点で判断するとよいでしょう。
- 複数サーバー・複数プロセスから同時に強く書き込む必要があるか?
→ ある場合はMySQL/PostgreSQL一択。SQLiteは選択肢から外れる - 厳密なデータ型・高度な制約(外部キー、CHECK制約の徹底など)が必須か?
→ 必須ならPostgreSQL、実務での慣れやエコシステムを優先するならMySQL - 上記のいずれにも当てはまらず、単一プロセス・小規模・組み込み用途か?
→ SQLiteが最有力候補。セットアップコストのなさを最大限活かせる
「とりあえずMySQLを使っておけば安心」という判断は間違いではありませんが、小規模なツールやプロトタイプにまでサーバー型DBを持ち出すのは、開発体験としてはオーバースペックになりがちです。
実務での使い分け事例
プロトタイプはSQLite、本番はPostgreSQLへ移行した経験
私が受託した案件の中に、社内向けの簡易な在庫管理ツールをまず動くものとして素早く作ってほしい、という要望のものがありました。
要件も流動的だったため、最初のプロトタイプはSQLiteで組み、数日でデモできる状態に仕上げました。
その後、実際に複数拠点から同時にアクセスする本番運用が決まった時点で、PostgreSQLへの移行を提案しました。
-- SQLiteのデータをCSV経由でエクスポート
.headers on
.mode csv
.output inventory.csv
SELECT * FROM inventory;
# PostgreSQLへCSVをインポート
psql -d production_db -c "\COPY inventory FROM 'inventory.csv' WITH CSV HEADER"
SQLファイルの互換性は完全ではないため、型アフィニティで緩く保存されていたデータ(日付や真偽値など)の見直しが必要になりましたが、それでもゼロから設計し直すよりはるかに早く移行できました。
「まずSQLiteで素早く形にし、要件が固まった段階で必要ならサーバー型DBへ移行する」という進め方は、開発初期のスピードと本番の信頼性を両立させる、実務上有効な戦略だと感じています。
まとめ
この記事のポイント
- SQLiteとMySQL・PostgreSQLの最大の違いは「同時に強く書き込む前提があるかどうか」
- SQLiteはモバイル・デスクトップ・テスト環境・小規模ツール・IoTなど、単一プロセス寄りの用途に強い
- 複数サーバーからの共有アクセスが前提のWebサービス本番DBには、サーバー型DBが基本
- プロトタイプはSQLite、本番運用の要件が固まった段階でサーバー型DBへ移行する進め方も有効
これでSQLite編(全8本)は完結です。
ファイルベースの仕組みから型アフィニティ、トランザクション、インデックス、WALモード、バックアップ運用まで、SQLiteならではのポイントを一通り押さえていただけたなら嬉しいです。
次に読むべき記事
次回からは、ドキュメント指向のNoSQLデータベースであるMongoDB編に入ります。
SQLと発想がまったく異なるスキーマ設計・集約パイプラインの世界を、ぜひ引き続き学んでいきましょう。
→ 次のシリーズ:MongoDB編(近日公開)
タグ: SQLite, 中級者向け, 比較検証
