エンジニアの皆さん、普段の開発でMySQLやPostgreSQLを使いこなしていることと思います。「SQLite?それってモバイルアプリや小規模なプロジェクト向けのデータベースでしょ?」と感じている方も多いのではないでしょうか。
しかし、最近の技術の進歩により、SQLiteはプロダクション環境でも十分に活用できるデータベースとして再評価されています。実際に、SQLiteを使ったモダンなアプリケーションやサービスが増えてきています。
本記事では、SQLiteの最新の使い方や、その特徴をMySQLやPostgreSQLと比較しながら、プロダクション環境でどのように活用できるのかを詳しく解説します。
まずは、SQLiteがどのようなデータベースなのか、基本をおさらいしておきましょう。
- サーバーレスアーキテクチャ:専用のデータベースサーバーを必要とせず、アプリケーションに直接組み込んで使用できます。
- 軽量で高速:全体が数百KBのライブラリで構成され、非常に軽快に動作します。
- 単一ファイルでのデータ管理:データベース全体が一つのファイルに収まっているため、移動やバックアップが簡単です。
- ACID特性のサポート:トランザクション処理やデータ整合性も安心です。
これらの特徴から、小規模なアプリケーションやモバイルアプリで多く利用されています。しかし、「レプリケーションはどうするの?」「リモートからの接続は可能なの?」「ポイントインタイムリカバリ(PITR)は?」といった疑問もあるでしょう。次のセクションでは、これらの点について詳しく見ていきます。
まずは、SQLiteが他の主要なリレーショナルデータベースとどう違うのか、比較してみましょう。
特徴 | SQLite | MySQL/PostgreSQL |
---|---|---|
アーキテクチャ | サーバーレス、組み込み型 | クライアントサーバーモデル |
データ保存 | 単一ファイル | 複数ファイル、専用のデータディレクトリ |
同時接続性 | 同時書き込みに制限あり | 高い同時接続性 |
レプリケーション | 標準では非対応(サードパーティツールで実現可能) | マスター・スレーブ、マルチマスター構成が可能 |
リモート接続 | 標準では非対応(APIやサーバーで実現) | 標準で対応 |
PITR | 設定により可能 | 標準で対応 |
機能拡張性 | 基本的な機能に限定 | ストアドプロシージャ、レプリケーションなど豊富 |
この比較からもわかるように、SQLiteはシンプルで軽量な反面、標準ではレプリケーションやリモート接続などの機能が不足しています。しかし、近年はこれらの課題を解決するためのツールや手法が登場しており、プロダクション環境でも十分に使えるようになっています。
レプリケーションは、データの冗長性や可用性を高めるために重要です。SQLite自体は標準でレプリケーション機能を持っていませんが、サードパーティ製のツールを活用することで実現可能です。
Litestreamは、SQLiteのWAL(Write-Ahead Logging)ファイルをリアルタイムでオブジェクトストレージ(例:AWS S3)にレプリケートするツールです。これにより、データのバックアップと冗長化をシンプルに実現できます。
導入手順:
-
Litestreamのインストール
curl -L https://github.com/benbjohnson/litestream/releases/latest/download/litestream-$(uname -s)-$(uname -m) -o /usr/local/bin/litestream chmod +x /usr/local/bin/litestream
-
設定ファイルの作成
litestream.yml
を作成し、レプリケーション先を指定します。dbs: - path: /path/to/your/database.db replicas: - url: s3://your-bucket/path/
-
Litestreamの起動
litestream replicate -config litestream.yml
これで、データベースの変更がリアルタイムでS3に同期されます。万が一サーバーがダウンしても、最新のデータを迅速に復旧できます。
もう一つのアプローチとして、rqliteを使用して、SQLiteベースの分散データベースを構築する方法があります。rqliteはRaftアルゴリズムを用いてレプリケーションとフォールトトレランスを提供し、高可用性を実現します。
導入手順:
-
rqliteのダウンロード
wget https://github.com/rqlite/rqlite/releases/download/vX.X.X/rqlite-vX.X.X-linux-amd64.tar.gz tar xvf rqlite-vX.X.X-linux-amd64.tar.gz
-
ノードの起動
./rqlited -node-id node1 -http-addr localhost:4001 -raft-addr localhost:4002 /path/to/data
-
クラスタリングの設定
複数のノードを起動し、クラスタを形成します。
rqliteを使うことで、SQLiteのシンプルさを維持しながら、分散データベースのメリットを享受できます。
SQLiteはサーバーレスのため、標準ではリモートからの直接接続ができません。しかし、APIサーバーや専用のサーバーソフトウェアを介すことで、リモートアクセスが可能になります。
Datasetteは、SQLiteデータベースをWeb上で公開するためのツールです。簡単なコマンドでデータをWebインターフェースから閲覧・操作できます。
導入手順:
-
Datasetteのインストール
pip install datasette
-
サーバーの起動
datasette serve /path/to/database.db
-
アクセス
ブラウザで
http://localhost:8001
にアクセスすると、データベースの内容を確認できます。
また、FlaskやExpressなどのWebフレームワークを使って、SQLiteにアクセスするREST APIを自作することも可能です。これにより、柔軟なAPIエンドポイントを提供できます。
PythonとFlaskの例:
from flask import Flask, jsonify
import sqlite3
app = Flask(__name__)
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
@app.route('/users', methods=['GET'])
def get_users():
conn = get_db_connection()
users = conn.execute('SELECT * FROM users').fetchall()
conn.close()
return jsonify([dict(row) for row in users])
if __name__ == '__main__':
app.run()
このように、簡単なコードでリモートからデータにアクセスできるAPIを構築できます。
多くのプログラミング言語でSQLiteへの接続がサポートされており、既存のアプリケーションに組み込みやすいです。
- Python:
sqlite3
モジュール(標準ライブラリ) - Go:
github.com/mattn/go-sqlite3
- Ruby:
sqlite3
gem - Node.js:
better-sqlite3
など
Node.jsでの接続例:
const Database = require('better-sqlite3');
const db = new Database('database.db');
const rows = db.prepare('SELECT * FROM users').all();
console.log(rows);
シンプルなコードでデータベース操作が可能です。
データの安全性を高めるために、特定の時点にデータベースを復元できるPITRは重要です。SQLiteでも適切な設定と手順によりPITRを実現できます。
設定手順:
-
WALモードの有効化
PRAGMA journal_mode=WAL;
-
WALファイルのバックアップ
WALファイル(
*.db-wal
)を定期的に安全な場所にバックアップします。 -
復元手順
- 対応するデータベースファイルとWALファイルを取得します。
- 必要な時点までのWALファイルを適用して復元します。
注意点:
- WALファイルは自動的にチェックポイントされるため、バックアップのタイミングに注意が必要です。
プロダクション環境でのパフォーマンスは重要な要素です。SQLiteでも適切な設定とチューニングで性能を引き出せます。
クエリの高速化にはインデックスが欠かせません。頻繁に検索される列にインデックスを設定しましょう。
CREATE INDEX idx_users_email ON users(email);
-
キャッシュサイズの調整
メモリを増やしてキャッシュサイズを大きくすることで、I/Oを減らせます。
PRAGMA cache_size = 10000;
-
同期モードの変更
データ整合性とパフォーマンスのバランスを取ります。
PRAGMA synchronous = NORMAL;
複数のデータ操作を一つのトランザクションでまとめることで、パフォーマンスが向上します。
BEGIN TRANSACTION;
-- 複数のINSERTやUPDATE
COMMIT;
各サービスが独自のデータベースを持つ場合、SQLiteの軽量性とシンプルさがメリットになります。
AWS LambdaやGCP Cloud Functionsなどの環境でも、ローカルストレージとしてSQLiteを活用できます。
ネットワーク接続が不安定な環境でも、ローカルデータベースとして機能します。
リソースが限られたデバイス上でも動作し、ローカルでデータを処理できます。
SQLiteは同時書き込みに制限がありますが、WALモードを活用することである程度解消できます。
-
WALモードの有効化
PRAGMA journal_mode=WAL;
-
アプリケーションレベルでの工夫
書き込み操作をキューに入れるなど、同時書き込みを避ける設計が求められます。
-
ファイルシステムの権限管理
データベースファイルへのアクセス権限を適切に設定しましょう。
-
データベースの暗号化
SQLCipherを使用して、データを暗号化することができます。
-
定期的なバックアップ
バックアップAPIやファイルコピーを使って、データを安全に保管します。
-
ホットバックアップの活用
データベースを停止せずにバックアップを取得できます。
.backup main backup.db
SQLiteはその軽量性とシンプルさから、これまで小規模なアプリケーションで主に利用されてきました。しかし、レプリケーションやリモートアクセス、パフォーマンスチューニングなどの手法を取り入れることで、プロダクション環境でも十分に活用できるデータベースとなっています。
この記事を通じて、SQLiteをプロダクションで使うための具体的な方法やポイントをご理解いただけたかと思います。ぜひ、次のプロジェクトでSQLiteの可能性を探ってみてください。
- SQLite公式ドキュメント:https://www.sqlite.org/docs.html
- Litestream:https://litestream.io/
- rqlite:https://github.com/rqlite/rqlite
- Datasette:https://datasette.io/
- SQLCipher:https://www.zetetic.net/sqlcipher/